project leak
[fedora-idea.git] / plugins / svn4idea / src / org / jetbrains / idea / svn / SvnConfiguration.java
blob80ff7575b503ea4560749b430d885d049cb063ee
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.
18 package org.jetbrains.idea.svn;
20 import com.intellij.openapi.application.ApplicationManager;
21 import com.intellij.openapi.application.ModalityState;
22 import com.intellij.openapi.components.ProjectComponent;
23 import com.intellij.openapi.diagnostic.Logger;
24 import com.intellij.openapi.progress.ProcessCanceledException;
25 import com.intellij.openapi.progress.ProgressIndicator;
26 import com.intellij.openapi.progress.ProgressManager;
27 import com.intellij.openapi.project.Project;
28 import com.intellij.openapi.util.*;
29 import com.intellij.openapi.util.io.FileUtil;
30 import com.intellij.openapi.vcs.annotate.AnnotationListener;
31 import org.jdom.Attribute;
32 import org.jdom.DataConversionException;
33 import org.jdom.Element;
34 import org.jetbrains.idea.svn.dialogs.SvnAuthenticationProvider;
35 import org.jetbrains.idea.svn.update.MergeRootInfo;
36 import org.jetbrains.idea.svn.update.UpdateRootInfo;
37 import org.tmatesoft.svn.core.SVNDepth;
38 import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
39 import org.tmatesoft.svn.core.internal.wc.ISVNAuthenticationStorage;
40 import org.tmatesoft.svn.core.internal.wc.SVNConfigFile;
41 import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
42 import org.tmatesoft.svn.core.wc.ISVNOptions;
43 import org.tmatesoft.svn.core.wc.SVNWCUtil;
45 import java.io.File;
46 import java.io.FilenameFilter;
47 import java.util.*;
49 public class SvnConfiguration implements ProjectComponent, JDOMExternalizable {
50 private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.svn.SvnConfiguration");
52 private final static String SERVERS_FILE_NAME = "servers";
54 public static final String UPGRADE_AUTO = "auto";
55 public static final String UPGRADE_AUTO_15 = "auto1.5";
56 public static final String UPGRADE_AUTO_16 = "auto1.6";
57 public static final String UPGRADE_NONE = "none";
59 public String USER = "";
60 public String PASSWORD = "";
61 public String[] ADD_PATHS = null;
63 private String myConfigurationDirectory;
64 private boolean myIsUseDefaultConfiguration;
65 private boolean myIsUseDefaultProxy;
66 private ISVNOptions myOptions;
67 private boolean myIsKeepLocks;
68 private boolean myRemoteStatus;
69 private final Project myProject;
70 private SvnAuthenticationManager myAuthManager;
71 private String myUpgradeMode;
72 private SvnSupportOptions mySupportOptions;
74 public static final AuthStorage RUNTIME_AUTH_CACHE = new AuthStorage();
75 public String LAST_MERGED_REVISION = null;
76 public boolean UPDATE_RUN_STATUS = false;
77 public SVNDepth UPDATE_DEPTH = SVNDepth.INFINITY;
79 public boolean MERGE_DRY_RUN = false;
80 public boolean MERGE_DIFF_USE_ANCESTRY = true;
81 public boolean UPDATE_LOCK_ON_DEMAND = false;
82 public boolean IGNORE_SPACES_IN_MERGE = false;
83 public boolean DETECT_NESTED_COPIES = false;
84 public boolean IGNORE_SPACES_IN_ANNOTATE = true;
85 public boolean SHOW_MERGE_SOURCES_IN_ANNOTATE = true;
87 private final Map<File, MergeRootInfo> myMergeRootInfos = new HashMap<File, MergeRootInfo>();
88 private final Map<File, UpdateRootInfo> myUpdateRootInfos = new HashMap<File, UpdateRootInfo>();
89 private final List<AnnotationListener> myAnnotationListeners;
91 public static SvnConfiguration getInstance(Project project) {
92 return project.getComponent(SvnConfiguration.class);
95 public static SvnConfiguration getInstanceChecked(final Project project) {
96 return ApplicationManager.getApplication().runReadAction(new Computable<SvnConfiguration>() {
97 public SvnConfiguration compute() {
98 if (project.isDisposed()) throw new ProcessCanceledException();
99 return project.getComponent(SvnConfiguration.class);
104 public SvnConfiguration(final Project project) {
105 myProject = project;
106 myAnnotationListeners = new ArrayList<AnnotationListener>();
109 // accessed on AWT
110 public void addAnnotationListener(final AnnotationListener listener) {
111 myAnnotationListeners.add(listener);
114 public void removeAnnotationListener(final AnnotationListener listener) {
115 myAnnotationListeners.remove(listener);
118 public void setIgnoreSpacesInAnnotate(final boolean value) {
119 final boolean changed = IGNORE_SPACES_IN_ANNOTATE != value;
120 IGNORE_SPACES_IN_ANNOTATE = value;
121 if (changed) {
122 fireForAnnotationListeners();
126 private void fireForAnnotationListeners() {
127 final AnnotationListener[] listeners = myAnnotationListeners.toArray(new AnnotationListener[myAnnotationListeners.size()]);
128 ApplicationManager.getApplication().invokeLater(new Runnable() {
129 public void run() {
130 for (int i = 0; i < listeners.length; i++) {
131 final AnnotationListener listener = listeners[i];
132 listener.onAnnotationChanged();
135 }, ModalityState.NON_MODAL);
138 public class SvnSupportOptions {
140 * version of "support SVN in IDEA". for features tracking. should grow
142 private Long myVersion;
144 public SvnSupportOptions(final Long version) {
145 myVersion = version;
146 // will be set to SvnSupportOptions.CHANGELIST_SUPPORT after sync
147 if (myVersion == null || myVersion.longValue() < SvnSupportOptions.CHANGELIST_SUPPORT) {
148 myVersion = SvnSupportOptions.UPGRADE_TO_15_VERSION_ASKED;
152 private final static long UPGRADE_TO_15_VERSION_ASKED = 123;
153 private final static long CHANGELIST_SUPPORT = 124;
154 private final static long UPGRADE_TO_16_VERSION_ASKED = 125;
156 public boolean upgradeTo16Asked() {
157 return (myVersion != null) && (UPGRADE_TO_16_VERSION_ASKED <= myVersion);
160 public boolean changeListsSynchronized() {
161 return (myVersion != null) && (CHANGELIST_SUPPORT <= myVersion);
164 public void upgrade() {
165 myVersion = UPGRADE_TO_16_VERSION_ASKED;
169 public SvnSupportOptions getSupportOptions() {
170 if (mySupportOptions == null) {
171 // used to be kept in SvnBranchConfigurationManager
172 mySupportOptions = new SvnSupportOptions(SvnBranchConfigurationManager.getInstance(myProject).getSupportValue());
174 return mySupportOptions;
177 public String getConfigurationDirectory() {
178 if (myConfigurationDirectory == null || isUseDefaultConfiguation()) {
179 myConfigurationDirectory = SVNWCUtil.getDefaultConfigurationDirectory().getAbsolutePath();
181 return myConfigurationDirectory;
184 public boolean isUseDefaultConfiguation() {
185 return myIsUseDefaultConfiguration;
188 public void setConfigurationDirectory(String path) {
189 myConfigurationDirectory = path;
190 File dir = path == null ? SVNWCUtil.getDefaultConfigurationDirectory() : new File(path);
191 SVNConfigFile.createDefaultConfiguration(dir);
193 myOptions = null;
194 myAuthManager = null;
195 RUNTIME_AUTH_CACHE.clear();
198 public void setUseDefaultConfiguation(boolean useDefault) {
199 myIsUseDefaultConfiguration = useDefault;
200 myOptions = null;
201 myAuthManager = null;
202 RUNTIME_AUTH_CACHE.clear();
205 public ISVNOptions getOptions(Project project) {
206 if (myOptions == null) {
207 File path = new File(getConfigurationDirectory());
208 myOptions = SVNWCUtil.createDefaultOptions(path.getAbsoluteFile(), true);
210 return myOptions;
213 public ISVNAuthenticationManager getAuthenticationManager(final SvnVcs svnVcs) {
214 if (myAuthManager == null) {
215 // reloaded when configuration directory changes
216 myAuthManager = new SvnAuthenticationManager(myProject, new File(getConfigurationDirectory()));
217 myAuthManager.setAuthenticationProvider(new SvnAuthenticationProvider(svnVcs));
218 myAuthManager.setRuntimeStorage(RUNTIME_AUTH_CACHE);
220 return myAuthManager;
223 public void getServerFilesManagers(final Ref<SvnServerFileManager> systemManager, final Ref<SvnServerFileManager> userManager) {
224 // created only if does not exist
225 SVNConfigFile.createDefaultConfiguration(new File(getConfigurationDirectory()));
227 systemManager.set(new SvnServerFileManagerImpl(new IdeaSVNConfigFile(new File(SVNFileUtil.getSystemConfigurationDirectory(), SERVERS_FILE_NAME))));
228 userManager.set(new SvnServerFileManagerImpl(new IdeaSVNConfigFile(new File(getConfigurationDirectory(), SERVERS_FILE_NAME))));
231 public String getUpgradeMode() {
232 return myUpgradeMode;
235 public void setUpgradeMode(String upgradeMode) {
236 myUpgradeMode = upgradeMode;
239 @SuppressWarnings({"HardCodedStringLiteral"})
240 public void readExternal(Element element) throws InvalidDataException {
241 DefaultJDOMExternalizer.readExternal(this, element);
242 List elems = element.getChildren("addpath");
243 LOG.debug(elems.toString());
244 ADD_PATHS = new String[elems.size()];
245 for (int i = 0; i < elems.size(); i++) {
246 Element elem = (Element)elems.get(i);
247 ADD_PATHS[i] = elem.getAttributeValue("path");
249 Element configurationDirectory = element.getChild("configuration");
250 if (configurationDirectory != null) {
251 myConfigurationDirectory = configurationDirectory.getText();
252 Attribute defaultAttr = configurationDirectory.getAttribute("useDefault");
253 try {
254 myIsUseDefaultConfiguration = defaultAttr != null && defaultAttr.getBooleanValue();
256 catch (DataConversionException e) {
257 myIsUseDefaultConfiguration = false;
260 else {
261 myIsUseDefaultConfiguration = true;
263 // compatibility: this setting was moved from .iws to global settings
264 List urls = element.getChildren("checkoutURL");
265 for (Object url1 : urls) {
266 Element child = (Element)url1;
267 String url = child.getText();
268 if (url != null) {
269 SvnApplicationSettings.getInstance().addCheckoutURL(url);
272 myIsKeepLocks = element.getChild("keepLocks") != null;
273 myRemoteStatus = element.getChild("remoteStatus") != null;
274 myUpgradeMode = element.getChild("upgradeMode") != null ? element.getChild("upgradeMode").getText() : null;
275 final Element useProxy = element.getChild("myIsUseDefaultProxy");
276 if (useProxy == null) {
277 myIsUseDefaultProxy = false;
278 } else {
279 myIsUseDefaultProxy = Boolean.parseBoolean(useProxy.getText());
281 final Element supportedVersion = element.getChild("supportedVersion");
282 if (supportedVersion != null) {
283 mySupportOptions = new SvnSupportOptions(Long.parseLong(supportedVersion.getText()));
287 @SuppressWarnings({"HardCodedStringLiteral"})
288 public void writeExternal(Element element) throws WriteExternalException {
289 DefaultJDOMExternalizer.writeExternal(this, element);
290 if (ADD_PATHS != null) {
291 for (String aADD_PATHS : ADD_PATHS) {
292 Element elem = new Element("addpath");
293 elem.setAttribute("path", aADD_PATHS);
294 element.addContent(elem);
297 if (myConfigurationDirectory != null) {
298 Element configurationDirectory = new Element("configuration");
299 configurationDirectory.setText(myConfigurationDirectory);
300 configurationDirectory.setAttribute("useDefault", myIsUseDefaultConfiguration ? "true" : "false");
301 element.addContent(configurationDirectory);
303 if (myIsKeepLocks) {
304 element.addContent(new Element("keepLocks"));
306 if (myRemoteStatus) {
307 element.addContent(new Element("remoteStatus"));
309 if (myUpgradeMode != null) {
310 element.addContent(new Element("upgradeMode").setText(myUpgradeMode));
312 element.addContent(new Element("myIsUseDefaultProxy").setText(myIsUseDefaultProxy ? "true" : "false"));
313 if (mySupportOptions != null) {
314 element.addContent(new Element("supportedVersion").setText("" + mySupportOptions.myVersion));
318 public void projectOpened() {
321 public void projectClosed() {
324 public String getComponentName() {
325 return "SvnConfiguration";
328 public void initComponent() {
331 public void disposeComponent() {
334 public boolean isKeepLocks() {
335 return myIsKeepLocks;
338 public void setKeepLocks(boolean keepLocks) {
339 myIsKeepLocks = keepLocks;
342 public boolean isRemoteStatus() {
343 return myRemoteStatus;
346 public void setRemoteStatus(boolean remote) {
347 myRemoteStatus = remote;
350 public boolean isIsUseDefaultProxy() {
351 return myIsUseDefaultProxy;
354 public void setIsUseDefaultProxy(final boolean isUseDefaultProxy) {
355 myIsUseDefaultProxy = isUseDefaultProxy;
358 public static class AuthStorage implements ISVNAuthenticationStorage {
360 private final Map<String, Object> myStorage = new Hashtable<String, Object>();
362 public void clear() {
363 myStorage.clear();
366 public void putData(String kind, String realm, Object data) {
367 if (data == null) {
368 myStorage.remove(kind + "$" + realm);
369 } else {
370 myStorage.put(kind + "$" + realm, data);
374 public Object getData(String kind, String realm) {
375 return myStorage.get(kind + "$" + realm);
379 public MergeRootInfo getMergeRootInfo(final File file, final SvnVcs svnVcs) {
380 if (!myMergeRootInfos.containsKey(file)) {
381 myMergeRootInfos.put(file, new MergeRootInfo(file, svnVcs));
383 return myMergeRootInfos.get(file);
386 public UpdateRootInfo getUpdateRootInfo(File file, final SvnVcs svnVcs) {
387 if (!myUpdateRootInfos.containsKey(file)) {
388 myUpdateRootInfos.put(file, new UpdateRootInfo(file, svnVcs));
390 return myUpdateRootInfos.get(file);
393 public Map<File, UpdateRootInfo> getUpdateInfosMap() {
394 return Collections.unmodifiableMap(myUpdateRootInfos);
397 private static final List<String> ourAuthKinds = Arrays.asList(ISVNAuthenticationManager.PASSWORD, ISVNAuthenticationManager.SSH,
398 ISVNAuthenticationManager.SSL, ISVNAuthenticationManager.USERNAME, "svn.ssl.server");
400 public void clearAuthenticationDirectory() {
401 final File authDir = new File(getConfigurationDirectory(), "auth");
402 if (authDir.exists()) {
403 ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
404 public void run() {
405 final ProgressIndicator ind = ProgressManager.getInstance().getProgressIndicator();
406 if (ind != null) {
407 ind.setIndeterminate(true);
408 ind.setText("Clearing stored credentials in " + authDir.getAbsolutePath());
410 final File[] files = authDir.listFiles(new FilenameFilter() {
411 public boolean accept(File dir, String name) {
412 return ourAuthKinds.contains(name);
416 for (File dir : files) {
417 if (ind != null) {
418 ind.setText("Deleting " + dir.getAbsolutePath());
420 FileUtil.delete(dir);
423 }, "button.text.clear.authentication.cache", false, myProject);