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() + ")";
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
) {
164 public boolean isOutsideCopies() {
165 return myOutsideCopies
;
168 public void setOutsideCopies(boolean outsideCopies
) {
169 myOutsideCopies
= outsideCopies
;
172 public SVNURL
getWcUrl() {
176 public void setWcUrl(SVNURL wcUrl
) {
180 public String
getKind() {
184 public SVNURL
getUrl() {
188 public String
getRealm() {
193 static void log(final Throwable t
) {
197 static void log(final String 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();
219 new SVNWCClient(manager
, configuration
.getOptions(project
)).doInfo(url
, SVNRevision
.UNDEFINED
, SVNRevision
.HEAD
);
220 } catch (SVNAuthenticationException e
) {
223 } catch (SVNCancelException e
) {
224 log(e
); // auth canceled
226 } catch (SVNException e
) {
227 if (e
.getErrorMessage().getErrorCode().isAuthentication()) {
231 LOG
.info("some other exc", e
);
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
);
250 configuration.getAuthenticationManager(svnVcs).acknowledgeAuthentication(true, kind, realm, null, svnAuthentication);
252 catch (SVNException e) {
254 // acknowledge at least in runtime
255 configuration.acknowledge(kind, realm, svnAuthentication);