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
);
50 myRootsToWorkingCopies
= myVcs
.getRootsToWorkingCopies();
54 protected boolean ask(final AuthenticationRequest obj
) {
55 final Ref
<Boolean
> resultRef
= new Ref
<Boolean
>();
56 final boolean done
= ProgressManager
.getInstance().runProcessWithProgressSynchronously(new Runnable() {
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
);
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() {
73 myVcs.invokeRefreshSvnRoots(false);
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() {
91 for (SVNURL key : outdatedRequests) {
92 removeLazyNotificationByKey(key);
95 }, ModalityState.NON_MODAL); */
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
);
107 public SVNURL
getKey(final AuthenticationRequest obj
) {
109 return obj
.getWcUrl();
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());
119 obj
.setOutsideCopies(false);
120 obj
.setWcUrl(copy
.getUrl());
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
;
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
) {
158 public boolean isOutsideCopies() {
159 return myOutsideCopies
;
162 public void setOutsideCopies(boolean outsideCopies
) {
163 myOutsideCopies
= outsideCopies
;
166 public SVNURL
getWcUrl() {
170 public void setWcUrl(SVNURL wcUrl
) {
174 public String
getKind() {
178 public SVNURL
getUrl() {
182 public String
getRealm() {
187 static void log(final Throwable t
) {
191 static void log(final String 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();
213 new SVNWCClient(manager
, configuration
.getOptions(project
)).doInfo(url
, SVNRevision
.UNDEFINED
, SVNRevision
.HEAD
);
214 } catch (SVNAuthenticationException e
) {
217 } catch (SVNCancelException e
) {
218 log(e
); // auth canceled
220 } catch (SVNException e
) {
221 if (e
.getErrorMessage().getErrorCode().isAuthentication()) {
225 LOG
.info("some other exc", e
);
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
);
244 configuration.getAuthenticationManager(svnVcs).acknowledgeAuthentication(true, kind, realm, null, svnAuthentication);
246 catch (SVNException e) {
248 // acknowledge at least in runtime
249 configuration.acknowledge(kind, realm, svnAuthentication);