IDEA-26360 (Performance and inconsistency issues with svn:externals and "Detect neste...
[fedora-idea.git] / plugins / svn4idea / src / org / jetbrains / idea / svn / SvnAuthenticationNotifier.java
blobe28d5dc51020cda699ca60330b81e38c43dbd5cb
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.jetbrains.idea.svn;
18 import com.intellij.notification.NotificationType;
19 import com.intellij.openapi.diagnostic.Logger;
20 import com.intellij.openapi.progress.ProgressManager;
21 import com.intellij.openapi.project.Project;
22 import com.intellij.openapi.ui.MessageType;
23 import com.intellij.openapi.util.Ref;
24 import com.intellij.openapi.vcs.changes.ui.ChangesViewBalloonProblemNotifier;
25 import com.intellij.openapi.vcs.impl.GenericNotifierImpl;
26 import com.intellij.openapi.vfs.VirtualFile;
27 import com.intellij.util.ThreeState;
28 import org.jetbrains.annotations.NotNull;
29 import org.jetbrains.annotations.Nullable;
30 import org.jetbrains.idea.svn.dialogs.SvnInteractiveAuthenticationProvider;
31 import org.tmatesoft.svn.core.SVNAuthenticationException;
32 import org.tmatesoft.svn.core.SVNCancelException;
33 import org.tmatesoft.svn.core.SVNException;
34 import org.tmatesoft.svn.core.SVNURL;
35 import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
36 import org.tmatesoft.svn.core.auth.SVNAuthentication;
37 import org.tmatesoft.svn.core.wc.SVNRevision;
38 import org.tmatesoft.svn.core.wc.SVNWCClient;
40 public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthenticationNotifier.AuthenticationRequest, SVNURL> {
41 private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnAuthenticationNotifier");
43 private static final String ourGroupId = "Subversion";
44 private final SvnVcs myVcs;
45 private final RootsToWorkingCopies myRootsToWorkingCopies;
47 public SvnAuthenticationNotifier(final SvnVcs svnVcs) {
48 super(svnVcs.getProject(), ourGroupId, "Not Logged To Subversion", NotificationType.ERROR);
49 myVcs = svnVcs;
50 myRootsToWorkingCopies = myVcs.getRootsToWorkingCopies();
53 @Override
54 protected boolean ask(final AuthenticationRequest obj) {
55 final Ref<Boolean> resultRef = new Ref<Boolean>();
56 final boolean done = ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
57 public void run() {
58 final boolean result = interactiveValidation(obj.myProject, obj.getUrl(), obj.getRealm(), obj.getKind());
59 log("ask result for: " + obj.getUrl() + " is: " + result);
60 resultRef.set(result);
61 if (result) {
62 onStateChangedToSuccess(obj);
65 }, "Checking authorization state", true, myVcs.getProject());
66 return done && Boolean.TRUE.equals(resultRef.get());
69 private void onStateChangedToSuccess(final AuthenticationRequest obj) {
70 myVcs.invokeRefreshSvnRoots(false);
71 /*ApplicationManager.getApplication().invokeLater(new Runnable() {
72 public void run() {
73 myVcs.invokeRefreshSvnRoots(false);
75 });*/
77 /*final List<SVNURL> outdatedRequests = new LinkedList<SVNURL>();
78 final Collection<SVNURL> keys = getAllCurrentKeys();
79 for (SVNURL key : keys) {
80 final SVNURL commonURLAncestor = SVNURLUtil.getCommonURLAncestor(key, obj.getUrl());
81 if ((! StringUtil.isEmptyOrSpaces(commonURLAncestor.getHost())) && (! StringUtil.isEmptyOrSpaces(commonURLAncestor.getPath()))) {
82 final AuthenticationRequest currObj = getObj(key);
83 if ((currObj != null) && passiveValidation(myVcs.getProject(), key, true, currObj.getRealm(), currObj.getKind())) {
84 outdatedRequests.add(key);
88 log("on state changed ");
89 ApplicationManager.getApplication().invokeLater(new Runnable() {
90 public void run() {
91 for (SVNURL key : outdatedRequests) {
92 removeLazyNotificationByKey(key);
95 }, ModalityState.NON_MODAL); */
98 @Override
99 public void ensureNotify(AuthenticationRequest obj) {
100 ChangesViewBalloonProblemNotifier.showMe(myVcs.getProject(), "You are not authenticated to '" + obj.getRealm() + "'." +
101 "To login, see pending notifications.", MessageType.ERROR);
102 super.ensureNotify(obj);
105 @NotNull
106 @Override
107 public SVNURL getKey(final AuthenticationRequest obj) {
108 // !!! wc's URL
109 return obj.getWcUrl();
112 @Nullable
113 public SVNURL getWcUrl(final AuthenticationRequest obj) {
114 if (obj.isOutsideCopies()) return null;
115 if (obj.getWcUrl() != null) return obj.getWcUrl();
117 final WorkingCopy copy = myRootsToWorkingCopies.getMatchingCopy(obj.getUrl());
118 if (copy != null) {
119 obj.setOutsideCopies(false);
120 obj.setWcUrl(copy.getUrl());
121 } else {
122 obj.setOutsideCopies(true);
124 return copy == null ? null : copy.getUrl();
128 * Bases on presence of notifications!
130 public ThreeState isAuthenticatedFor(final VirtualFile vf) {
131 final WorkingCopy wcCopy = myRootsToWorkingCopies.getWcRoot(vf);
132 if (wcCopy == null) return ThreeState.UNSURE;
133 return getStateFor(wcCopy.getUrl()) ? ThreeState.NO : ThreeState.YES;
136 @NotNull
137 @Override
138 protected String getNotificationContent(AuthenticationRequest obj) {
139 return "<a href=\"\">Click to fix.</a> Not logged to Subversion '" + obj.getRealm() + "' (" + obj.getUrl().toDecodedString() + ")";
142 public static class AuthenticationRequest {
143 private final Project myProject;
144 private final String myKind;
145 private final SVNURL myUrl;
146 private final String myRealm;
148 private SVNURL myWcUrl;
149 private boolean myOutsideCopies;
151 public AuthenticationRequest(Project project, String kind, SVNURL url, String realm) {
152 myProject = project;
153 myKind = kind;
154 myUrl = url;
155 myRealm = realm;
158 public boolean isOutsideCopies() {
159 return myOutsideCopies;
162 public void setOutsideCopies(boolean outsideCopies) {
163 myOutsideCopies = outsideCopies;
166 public SVNURL getWcUrl() {
167 return myWcUrl;
170 public void setWcUrl(SVNURL wcUrl) {
171 myWcUrl = wcUrl;
174 public String getKind() {
175 return myKind;
178 public SVNURL getUrl() {
179 return myUrl;
182 public String getRealm() {
183 return myRealm;
187 static void log(final Throwable t) {
188 LOG.debug(t);
191 static void log(final String s) {
192 LOG.debug(s);
195 public static boolean passiveValidation(final Project project, final SVNURL url, final boolean checkWrite,
196 final String realm, final String kind) {
197 final SvnConfiguration configuration = SvnConfiguration.getInstance(project);
198 final ISVNAuthenticationManager passiveManager = configuration.getPassiveAuthenticationManager();
199 return validationImpl(project, url, configuration, passiveManager, checkWrite, realm, kind);
202 public static boolean interactiveValidation(final Project project, final SVNURL url, final String realm, final String kind) {
203 final SvnConfiguration configuration = SvnConfiguration.getInstance(project);
204 final ISVNAuthenticationManager passiveManager = configuration.getInteractiveManager(SvnVcs.getInstance(project));
205 return validationImpl(project, url, configuration, passiveManager, true, realm, kind);
208 private static boolean validationImpl(final Project project, final SVNURL url,
209 final SvnConfiguration configuration, final ISVNAuthenticationManager manager,
210 final boolean checkWrite, final String realm, final String kind/*, final boolean passive*/) {
211 SvnInteractiveAuthenticationProvider.clearCallState();
212 try {
213 new SVNWCClient(manager, configuration.getOptions(project)).doInfo(url, SVNRevision.UNDEFINED, SVNRevision.HEAD);
214 } catch (SVNAuthenticationException e) {
215 log(e);
216 return false;
217 } catch (SVNCancelException e) {
218 log(e); // auth canceled
219 return false;
220 } catch (SVNException e) {
221 if (e.getErrorMessage().getErrorCode().isAuthentication()) {
222 log(e);
223 return false;
225 LOG.info("some other exc", e);
227 if (! checkWrite) {
228 return true;
230 /*if (passive) {
231 return SvnInteractiveAuthenticationProvider.wasCalled();
234 if (SvnInteractiveAuthenticationProvider.wasCalled() && SvnInteractiveAuthenticationProvider.wasCancelled()) return false;
235 if (SvnInteractiveAuthenticationProvider.wasCalled()) return true;
237 final SvnVcs svnVcs = SvnVcs.getInstance(project);
239 final SvnInteractiveAuthenticationProvider provider = new SvnInteractiveAuthenticationProvider(svnVcs);
240 final SVNAuthentication svnAuthentication = provider.requestClientAuthentication(kind, url, realm, null, null, true);
241 if (svnAuthentication != null) {
242 configuration.acknowledge(kind, realm, svnAuthentication);
243 /*try {
244 configuration.getAuthenticationManager(svnVcs).acknowledgeAuthentication(true, kind, realm, null, svnAuthentication);
246 catch (SVNException e) {
247 LOG.info(e);
248 // acknowledge at least in runtime
249 configuration.acknowledge(kind, realm, svnAuthentication);
251 return true;
253 return false;