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
.openapi
.application
.ApplicationManager
;
19 import com
.intellij
.openapi
.project
.Project
;
20 import com
.intellij
.openapi
.ui
.MessageType
;
21 import com
.intellij
.openapi
.vcs
.changes
.ui
.ChangesViewBalloonProblemNotifier
;
22 import com
.intellij
.util
.containers
.SoftHashMap
;
23 import com
.intellij
.util
.net
.HttpConfigurable
;
24 import org
.tmatesoft
.svn
.core
.SVNErrorMessage
;
25 import org
.tmatesoft
.svn
.core
.SVNException
;
26 import org
.tmatesoft
.svn
.core
.SVNURL
;
27 import org
.tmatesoft
.svn
.core
.auth
.ISVNAuthenticationProvider
;
28 import org
.tmatesoft
.svn
.core
.auth
.ISVNProxyManager
;
29 import org
.tmatesoft
.svn
.core
.auth
.SVNAuthentication
;
30 import org
.tmatesoft
.svn
.core
.internal
.wc
.DefaultSVNAuthenticationManager
;
31 import org
.tmatesoft
.svn
.core
.internal
.wc
.DefaultSVNOptions
;
32 import org
.tmatesoft
.svn
.core
.io
.SVNRepository
;
35 import java
.util
.Iterator
;
37 import java
.util
.StringTokenizer
;
42 public class SvnAuthenticationManager
extends DefaultSVNAuthenticationManager
{
43 private final Project myProject
;
44 private PersistentAuthenticationProviderProxy myPersistentAuthenticationProviderProxy
;
46 public SvnAuthenticationManager(final Project project
, final File configDirectory
) {
47 super(configDirectory
, true, null, null);
49 if (myPersistentAuthenticationProviderProxy
!= null) {
50 myPersistentAuthenticationProviderProxy
.setProject(myProject
);
54 protected ISVNAuthenticationProvider
createCacheAuthenticationProvider(File authDir
) {
55 myPersistentAuthenticationProviderProxy
= new PersistentAuthenticationProviderProxy(super.createCacheAuthenticationProvider(authDir
, null));
56 return myPersistentAuthenticationProviderProxy
;
59 private static class PersistentAuthenticationProviderProxy
implements ISVNAuthenticationProvider
, IPersistentAuthenticationProvider
{
60 private final Map
<SvnAuthWrapperEqualable
, Long
> myRewritePreventer
;
61 private static final long ourRefreshInterval
= 6000 * 1000;
62 private final ISVNAuthenticationProvider myDelegate
;
63 private Project myProject
;
65 private PersistentAuthenticationProviderProxy(final ISVNAuthenticationProvider delegate
) {
66 myDelegate
= delegate
;
67 myRewritePreventer
= new SoftHashMap
<SvnAuthWrapperEqualable
, Long
>();
70 public void setProject(Project project
) {
74 public SVNAuthentication
requestClientAuthentication(final String kind
, final SVNURL url
, final String realm
, final SVNErrorMessage errorMessage
,
75 final SVNAuthentication previousAuth
,
76 final boolean authMayBeStored
) {
77 return myDelegate
.requestClientAuthentication(kind
, url
, realm
, errorMessage
, previousAuth
, authMayBeStored
);
80 public int acceptServerAuthentication(final SVNURL url
, final String realm
, final Object certificate
, final boolean resultMayBeStored
) {
81 return ACCEPTED_TEMPORARY
;
84 public void saveAuthentication(final SVNAuthentication auth
, final String kind
, final String realm
) throws SVNException
{
86 final SvnAuthWrapperEqualable newKey
= new SvnAuthWrapperEqualable(auth
);
87 final Long recent
= myRewritePreventer
.get(newKey
);
88 final long currTime
= System
.currentTimeMillis();
89 if (recent
== null || ((recent
!= null) && ((currTime
- recent
.longValue()) > ourRefreshInterval
))) {
90 ((IPersistentAuthenticationProvider
) myDelegate
).saveAuthentication(auth
, kind
, realm
);
91 myRewritePreventer
.put(newKey
, currTime
);
94 catch (final SVNException e
) {
95 // show notification so that user was aware his credentials were not saved
96 if (myProject
== null) return;
97 ApplicationManager
.getApplication().invokeLater(new ChangesViewBalloonProblemNotifier(myProject
,
98 "<b>Problem when storing Subversion credentials:</b> " + e
.getMessage(), MessageType
.ERROR
));
103 public ISVNProxyManager
getProxyManager(SVNURL url
) throws SVNException
{
104 // this code taken from default manager (changed for system properties reading)
105 String host
= url
.getHost();
107 Map properties
= getHostProperties(host
);
108 String proxyHost
= (String
) properties
.get("http-proxy-host");
109 if ((proxyHost
== null) || "".equals(proxyHost
.trim())) {
110 if (SvnConfiguration
.getInstanceChecked(myProject
).isIsUseDefaultProxy()) {
111 // ! use common proxy if it is set
112 final HttpConfigurable httpConfigurable
= HttpConfigurable
.getInstance();
113 final String ideaWideProxyHost
= httpConfigurable
.PROXY_HOST
;
114 String ideaWideProxyPort
= String
.valueOf(httpConfigurable
.PROXY_PORT
);
116 if (ideaWideProxyPort
== null) {
117 ideaWideProxyPort
= "3128";
120 if ((ideaWideProxyHost
!= null) && (! "".equals(ideaWideProxyHost
.trim()))) {
121 return new MyPromptingProxyManager(ideaWideProxyHost
, ideaWideProxyPort
);
126 String proxyExceptions
= (String
) properties
.get("http-proxy-exceptions");
127 String proxyExceptionsSeparator
= ",";
128 if (proxyExceptions
== null) {
129 proxyExceptions
= System
.getProperty("http.nonProxyHosts");
130 proxyExceptionsSeparator
= "|";
132 if (proxyExceptions
!= null) {
133 for(StringTokenizer exceptions
= new StringTokenizer(proxyExceptions
, proxyExceptionsSeparator
); exceptions
.hasMoreTokens();) {
134 String exception
= exceptions
.nextToken().trim();
135 if (DefaultSVNOptions
.matches(exception
, host
)) {
140 String proxyPort
= (String
) properties
.get("http-proxy-port");
141 String proxyUser
= (String
) properties
.get("http-proxy-username");
142 String proxyPassword
= (String
) properties
.get("http-proxy-password");
143 return new MySimpleProxyManager(proxyHost
, proxyPort
, proxyUser
, proxyPassword
);
146 private static class MyPromptingProxyManager
extends MySimpleProxyManager
{
147 private static final String ourPrompt
= "Proxy authentication";
149 private MyPromptingProxyManager(final String host
, final String port
) {
150 super(host
, port
, null, null);
154 public String
getProxyUserName() {
155 if (myProxyUser
!= null) {
158 final HttpConfigurable httpConfigurable
= HttpConfigurable
.getInstance();
159 if (httpConfigurable
.PROXY_AUTHENTICATION
&& (! httpConfigurable
.KEEP_PROXY_PASSWORD
)) {
160 httpConfigurable
.getPromptedAuthentication(myProxyHost
, ourPrompt
);
162 myProxyUser
= httpConfigurable
.PROXY_LOGIN
;
167 public String
getProxyPassword() {
168 if (myProxyPassword
!= null) {
169 return myProxyPassword
;
171 final HttpConfigurable httpConfigurable
= HttpConfigurable
.getInstance();
172 if (httpConfigurable
.PROXY_AUTHENTICATION
&& (! httpConfigurable
.KEEP_PROXY_PASSWORD
)) {
173 httpConfigurable
.getPromptedAuthentication(myProxyUser
, ourPrompt
);
175 myProxyPassword
= httpConfigurable
.getPlainProxyPassword();
176 return myProxyPassword
;
180 private static class MySimpleProxyManager
implements ISVNProxyManager
{
181 protected String myProxyHost
;
182 private final String myProxyPort
;
183 protected String myProxyUser
;
184 protected String myProxyPassword
;
186 public MySimpleProxyManager(String host
, String port
, String user
, String password
) {
188 myProxyPort
= port
== null ?
"3128" : port
;
190 myProxyPassword
= password
;
193 public String
getProxyHost() {
197 public int getProxyPort() {
199 return Integer
.parseInt(myProxyPort
);
200 } catch (NumberFormatException nfe
) {
206 public String
getProxyUserName() {
210 public String
getProxyPassword() {
211 return myProxyPassword
;
214 public void acknowledgeProxyContext(boolean accepted
, SVNErrorMessage errorMessage
) {
219 private final static int DEFAULT_READ_TIMEOUT
= 30 * 1000;
222 public int getReadTimeout(final SVNRepository repository
) {
223 String protocol
= repository
.getLocation().getProtocol();
224 if ("http".equals(protocol
) || "https".equals(protocol
)) {
225 String host
= repository
.getLocation().getHost();
226 Map properties
= getHostProperties(host
);
227 String timeout
= (String
) properties
.get("http-timeout");
228 if (timeout
!= null) {
230 return Integer
.parseInt(timeout
)*1000;
231 } catch (NumberFormatException nfe
) {
235 return DEFAULT_READ_TIMEOUT
;
240 // taken from default manager as is
241 private Map
getHostProperties(String host
) {
242 Map globalProps
= getServersFile().getProperties("global");
243 String groupName
= getGroupName(getServersFile().getProperties("groups"), host
);
244 if (groupName
!= null) {
245 Map hostProps
= getServersFile().getProperties(groupName
);
246 globalProps
.putAll(hostProps
);
251 public static boolean checkHostGroup(final String url
, final String patterns
, final String exceptions
) {
254 svnurl
= SVNURL
.parseURIEncoded(url
);
256 catch (SVNException e
) {
260 final String host
= svnurl
.getHost();
261 return matches(patterns
, host
) && (! matches(exceptions
, host
));
264 private static boolean matches(final String pattern
, final String host
) {
265 final StringTokenizer tokenizer
= new StringTokenizer(pattern
, ",");
266 while(tokenizer
.hasMoreTokens()) {
267 String token
= tokenizer
.nextToken();
268 if (DefaultSVNOptions
.matches(token
, host
)) {
275 // taken from default manager as is
276 private static String
getGroupName(Map groups
, String host
) {
277 for (Iterator names
= groups
.keySet().iterator(); names
.hasNext();) {
278 String name
= (String
) names
.next();
279 String pattern
= (String
) groups
.get(name
);
280 for(StringTokenizer tokens
= new StringTokenizer(pattern
, ","); tokens
.hasMoreTokens();) {
281 String token
= tokens
.nextToken();
282 if (DefaultSVNOptions
.matches(token
, host
)) {
290 private static class SvnAuthWrapperEqualable
extends Wrapper
<SVNAuthentication
> {
291 private SvnAuthWrapperEqualable(SVNAuthentication svnAuthentication
) {
292 super(svnAuthentication
);
296 public boolean equals(Object obj
) {
297 if (obj
== null) return false;
298 if (this == obj
) return true;
299 if (obj
instanceof SvnAuthWrapperEqualable
) {
300 return SvnAuthEquals
.equals(this.getT(), ((SvnAuthWrapperEqualable
) obj
).getT());
306 public int hashCode() {
307 return SvnAuthEquals
.hashCode(getT());