IDEA-51354 (Not logged to SVN notification: allow to copy message to clipboard)
[fedora-idea.git] / plugins / svn4idea / src / org / jetbrains / idea / svn / SvnAuthenticationNotifier.java
blob8002b0b2ce55a4a920658903c780b249e16bbfcf
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 @NotNull
143 @Override
144 protected String getToString(AuthenticationRequest obj) {
145 return "Click to fix. Not logged to Subversion '" + obj.getRealm() + "' (" + obj.getUrl().toDecodedString() + ")";
148 public static class AuthenticationRequest {
149 private final Project myProject;
150 private final String myKind;
151 private final SVNURL myUrl;
152 private final String myRealm;
154 private SVNURL myWcUrl;
155 private boolean myOutsideCopies;
157 public AuthenticationRequest(Project project, String kind, SVNURL url, String realm) {
158 myProject = project;
159 myKind = kind;
160 myUrl = url;
161 myRealm = realm;
164 public boolean isOutsideCopies() {
165 return myOutsideCopies;
168 public void setOutsideCopies(boolean outsideCopies) {
169 myOutsideCopies = outsideCopies;
172 public SVNURL getWcUrl() {
173 return myWcUrl;
176 public void setWcUrl(SVNURL wcUrl) {
177 myWcUrl = wcUrl;
180 public String getKind() {
181 return myKind;
184 public SVNURL getUrl() {
185 return myUrl;
188 public String getRealm() {
189 return myRealm;
193 static void log(final Throwable t) {
194 LOG.debug(t);
197 static void log(final String s) {
198 LOG.debug(s);
201 public static boolean passiveValidation(final Project project, final SVNURL url, final boolean checkWrite,
202 final String realm, final String kind) {
203 final SvnConfiguration configuration = SvnConfiguration.getInstance(project);
204 final ISVNAuthenticationManager passiveManager = configuration.getPassiveAuthenticationManager();
205 return validationImpl(project, url, configuration, passiveManager, checkWrite, realm, kind);
208 public static boolean interactiveValidation(final Project project, final SVNURL url, final String realm, final String kind) {
209 final SvnConfiguration configuration = SvnConfiguration.getInstance(project);
210 final ISVNAuthenticationManager passiveManager = configuration.getInteractiveManager(SvnVcs.getInstance(project));
211 return validationImpl(project, url, configuration, passiveManager, true, realm, kind);
214 private static boolean validationImpl(final Project project, final SVNURL url,
215 final SvnConfiguration configuration, final ISVNAuthenticationManager manager,
216 final boolean checkWrite, final String realm, final String kind/*, final boolean passive*/) {
217 SvnInteractiveAuthenticationProvider.clearCallState();
218 try {
219 new SVNWCClient(manager, configuration.getOptions(project)).doInfo(url, SVNRevision.UNDEFINED, SVNRevision.HEAD);
220 } catch (SVNAuthenticationException e) {
221 log(e);
222 return false;
223 } catch (SVNCancelException e) {
224 log(e); // auth canceled
225 return false;
226 } catch (SVNException e) {
227 if (e.getErrorMessage().getErrorCode().isAuthentication()) {
228 log(e);
229 return false;
231 LOG.info("some other exc", e);
233 if (! checkWrite) {
234 return true;
236 /*if (passive) {
237 return SvnInteractiveAuthenticationProvider.wasCalled();
240 if (SvnInteractiveAuthenticationProvider.wasCalled() && SvnInteractiveAuthenticationProvider.wasCancelled()) return false;
241 if (SvnInteractiveAuthenticationProvider.wasCalled()) return true;
243 final SvnVcs svnVcs = SvnVcs.getInstance(project);
245 final SvnInteractiveAuthenticationProvider provider = new SvnInteractiveAuthenticationProvider(svnVcs);
246 final SVNAuthentication svnAuthentication = provider.requestClientAuthentication(kind, url, realm, null, null, true);
247 if (svnAuthentication != null) {
248 configuration.acknowledge(kind, realm, svnAuthentication);
249 /*try {
250 configuration.getAuthenticationManager(svnVcs).acknowledgeAuthentication(true, kind, realm, null, svnAuthentication);
252 catch (SVNException e) {
253 LOG.info(e);
254 // acknowledge at least in runtime
255 configuration.acknowledge(kind, realm, svnAuthentication);
257 return true;
259 return false;