KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > subversion > config > SvnConfigFiles


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.subversion.config;
20
21 import java.io.File JavaDoc;
22 import java.io.FileNotFoundException JavaDoc;
23 import java.io.FileReader JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.net.InetSocketAddress JavaDoc;
26 import java.net.Proxy JavaDoc;
27 import java.net.ProxySelector JavaDoc;
28 import java.net.SocketAddress JavaDoc;
29 import java.net.URISyntaxException JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.StringTokenizer JavaDoc;
34 import java.util.prefs.Preferences JavaDoc;
35 import org.ini4j.Ini;
36 import org.netbeans.modules.subversion.util.FileUtils;
37 import org.openide.ErrorManager;
38 import org.openide.filesystems.FileUtil;
39 import org.openide.util.Utilities;
40
41 /**
42  *
43  * Handles the Subversions <b>servers</b> and <b>config</b> configuration files.</br>
44  * Everytime the singleton instance is created are the values from the commandline clients
45  * configuration directory merged into the Subversion modules configuration files.
46  * (registry on windows are ignored).
47  * Already present proxy setting values wan't be changed,
48  * the remaining values are always taken from the commandline clients configuration files.
49  * The only exception is the 'store-auth-creds' key, which is always set to 'no'.
50  *
51  * @author Tomas Stupka
52  */

53 public class SvnConfigFiles {
54
55     /** the only SvnConfigFiles instance */
56     private static SvnConfigFiles instance;
57
58     /** the Ini instance holding the configuration values stored in the <b>servers</b>
59      * file used by the Subversion module */

60     private Ini svnServers = null;
61     
62     /** the Ini instance holding the configuration values stored in the <b>config</b>
63      * file used by the Subversion module */

64     private Ini config = null;
65
66     private static final String JavaDoc UNIX_CONFIG_DIR = ".subversion/"; // NOI18N
67
private static final String JavaDoc GROUPS_SECTION = "groups"; // NOI18N
68
private static final String JavaDoc GLOBAL_SECTION = "global"; // NOI18N
69
private static final String JavaDoc WINDOWS_USER_APPDATA = getAPPDATA();
70     private static final String JavaDoc WINDOWS_CONFIG_DIR = WINDOWS_USER_APPDATA + "\\Subversion"; // NOI18N
71
private static final String JavaDoc WINDOWS_GLOBAL_CONFIG_DIR = getGlobalAPPDATA() + "\\Subversion"; // NOI18N
72
private static final List JavaDoc<String JavaDoc> DEFAULT_GLOBAL_IGNORES =
73             parseGlobalIgnores("*.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store"); // NOI18N
74

75     private interface IniFilePatcher {
76         void patch(Ini file);
77     }
78
79     /**
80      * The value for the 'store-auth-creds' key in the config cofiguration file is alway set to 'no'
81      * so the commandline client wan't create a file holding the authentication credentials when
82      * a svn command is called. The reason for this is that the Subverion module holds the credentials
83      * in files with the same format as the commandline client but with a different name.
84      */

85     private class ConfigIniFilePatcher implements IniFilePatcher {
86         public void patch(Ini file) {
87             // patch store-auth-creds to "no"
88
Ini.Section auth = (Ini.Section) file.get("auth"); // NOI18N
89
if(auth == null) {
90                 auth = file.add("auth"); // NOI18N
91
}
92             auth.put("store-auth-creds", "no"); // NOI18N
93
}
94     }
95
96     /**
97      * Creates a new instance
98      */

99     private SvnConfigFiles() {
100         // copy config file
101
config = copyConfigFileToIDEConfigDir("config", new ConfigIniFilePatcher()); // NOI18N
102
// get the system servers file
103
svnServers = loadSystemIniFile("servers");
104     }
105     
106     /**
107      * Returns a singleton instance.
108      *
109      * @return the SvnConfigFiles instance
110      */

111     public static SvnConfigFiles getInstance() {
112         if(instance==null) {
113             instance = new SvnConfigFiles();
114         }
115         return instance;
116     }
117
118     /**
119      * Stores the proxy host, port, username and password from the given
120      * {@link org.netbeans.modules.subversion.config.ProxyDescriptor} in the
121      * <b>servers</b> file used by the Subversion module.
122      *
123      * @param host the host
124      */

125     public void setProxy(String JavaDoc host) {
126      
127         assert host != null && !host.trim().equals(""): "can\'t do anything for a null host"; // NOI18N
128

129         if(host.startsWith("file:///")) {
130             // a proxy will be needed only for remote repositories
131
return;
132         }
133         
134         ProxySelector JavaDoc ps = ProxySelector.getDefault();
135         List JavaDoc<Proxy JavaDoc> proxies = null;
136         try {
137             proxies = ps.select(new java.net.URI JavaDoc(host));
138         } catch (URISyntaxException JavaDoc ex) {
139             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
140         }
141                                 
142         Proxy JavaDoc proxy = null;
143         for(Proxy JavaDoc p : proxies) {
144             if( p.type().equals(Proxy.Type.HTTP) ||
145                 p.type().equals(Proxy.Type.DIRECT) )
146             {
147                 proxy = p;
148                 if (proxy.type().equals(Proxy.Type.DIRECT)) {
149                     break;
150                 }
151             }
152         }
153         
154         Ini nbServers = new Ini();
155         Ini.Section nbGlobalSection = nbServers.add(GLOBAL_SECTION);
156         Ini.Section svnGlobalSection = svnServers.get(GLOBAL_SECTION);
157         if(proxy.type().equals(Proxy.Type.DIRECT)) {
158             // no proxy host means no proxy at all
159
if(svnGlobalSection != null) {
160                 // if there is a global section than get the no proxy settings
161
mergeNonProxyKeys(svnGlobalSection, nbGlobalSection);
162             }
163         } else {
164             // get the proxy
165
SocketAddress JavaDoc sa = proxy.address();
166             InetSocketAddress JavaDoc proxyAddress = (InetSocketAddress JavaDoc) sa;
167             
168             nbGlobalSection.put("http-proxy-host", proxyAddress.getHostName()); // NOI18N
169
nbGlobalSection.put("http-proxy-port", Integer.toString(proxyAddress.getPort())); // NOI18N
170

171             // and the authentication
172
Preferences JavaDoc prefs = org.openide.util.NbPreferences.root ().node ("org/netbeans/core"); // NOI18N
173
boolean useAuth = prefs.getBoolean ("useProxyAuthentication", false); // NOI18N
174
if(useAuth) {
175                 String JavaDoc username = prefs.get ("proxyAuthenticationUsername", ""); // NOI18N
176
String JavaDoc password = prefs.get ("proxyAuthenticationPassword", ""); // NOI18N
177

178                 nbGlobalSection.put("http-proxy-username", username); // NOI18N
179
nbGlobalSection.put("http-proxy-password", password); // NOI18N
180
}
181             
182             // we have a proxy for the host, so check
183
// if in the there are also some no proxy settings
184
// we should get from the original svn servers file
185
Ini.Section svnHostGroup = getServerGroup(host);
186             if(svnGlobalSection != null) {
187                 // if there is a global section than get the no proxy settings
188
mergeNonProxyKeys(svnGlobalSection, nbGlobalSection);
189             }
190             if(svnHostGroup != null) {
191                 mergeNonProxyKeys(svnHostGroup, nbGlobalSection);
192             }
193         }
194         storeIni(nbServers, "servers"); // NOI18N
195
}
196     
197     private void mergeNonProxyKeys(Ini.Section source, Ini.Section target) {
198         for (String JavaDoc key : source.keySet()) {
199             if(!isProxyConfigurationKey(key)) {
200                 target.put(key, source.get(key));
201             }
202         }
203     }
204     
205     public void setExternalCommand(String JavaDoc tunnelName, String JavaDoc command) {
206         Ini.Section tunnels = getSection(config, "tunnels", true);
207         tunnels.put(tunnelName, command);
208         storeIni(config, "config"); // NOI18N
209
}
210
211     public String JavaDoc getExternalCommand(String JavaDoc tunnelName) {
212         Ini.Section tunnels = getSection(config, "tunnels", true);
213         String JavaDoc cmd = tunnels.get(tunnelName);
214         return cmd != null ? cmd : "";
215     }
216     
217     private Ini.Section getSection(Ini ini, String JavaDoc key, boolean create) {
218         Ini.Section section = ini.get(key);
219         if(section == null) {
220             return ini.add(key);
221         }
222         return section;
223     }
224     
225     private void storeIni(Ini ini, String JavaDoc iniFile) {
226         try {
227             File JavaDoc file = FileUtil.normalizeFile(new File JavaDoc(getNBConfigPath() + "/" + iniFile)); // NOI18N
228
file.getParentFile().mkdirs();
229             ini.store(FileUtils.createOutputStream(file));
230         } catch (IOException JavaDoc ex) {
231             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
232         }
233     }
234
235     /**
236      * Returns the miscellany/global-ignores setting from the config file.
237      *
238      * @return a list with the inore patterns
239      *
240      */

241     public List JavaDoc<String JavaDoc> getGlobalIgnores() {
242         Ini.Section miscellany = config.get("miscellany"); // NOI18N
243
if (miscellany != null) {
244             String JavaDoc ignores = miscellany.get("global-ignores"); // NOI18N
245
if (ignores != null && ignores.trim().length() > 0) {
246                 return parseGlobalIgnores(ignores);
247             }
248         }
249         return DEFAULT_GLOBAL_IGNORES;
250     }
251
252     private static List JavaDoc<String JavaDoc> parseGlobalIgnores(String JavaDoc ignores) {
253         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(ignores, " "); // NOI18N
254
List JavaDoc<String JavaDoc> ret = new ArrayList JavaDoc<String JavaDoc>(10);
255         while (st.hasMoreTokens()) {
256             String JavaDoc entry = st.nextToken();
257             if (!entry.equals("")) // NOI18N
258
ret.add(entry);
259         }
260         return ret;
261     }
262
263     /**
264      * Returns the path for the Sunbversion configuration dicectory used
265      * by the systems Subversion commandline client.
266      *
267      * @return the path
268      *
269      */

270     public static String JavaDoc getUserConfigPath() {
271         if(Utilities.isUnix()) {
272             String JavaDoc path = System.getProperty("user.home") ; // NOI18N
273
return path + "/" + UNIX_CONFIG_DIR; // NOI18N
274
} else if (Utilities.isWindows()){
275             return WINDOWS_CONFIG_DIR;
276         }
277         return ""; // NOI18N
278
}
279
280     /**
281      * Returns the path for the Sunbversion configuration dicectory used
282      * by the Netbeans Subversion module.
283      *
284      * @return the path
285      *
286      */

287     public static String JavaDoc getNBConfigPath() {
288         String JavaDoc nbHome = System.getProperty("netbeans.user"); // NOI18N
289
return nbHome + "/config/svn/config/"; // NOI18N
290
}
291     
292     /**
293      * Returns the section from the <b>servers</b> config file used by the Subversion module which
294      * is holding the proxy settings for the given host
295      *
296      * @param host the host
297      * @return the section holding the proxy settings for the given host
298      */

299     private Ini.Section getServerGroup(String JavaDoc host) {
300         if(host == null || host.equals("")) { // NOI18N
301
return null;
302         }
303         Ini.Section groups = svnServers.get(GROUPS_SECTION);
304         if(groups != null) {
305             for (Iterator JavaDoc<String JavaDoc> it = groups.keySet().iterator(); it.hasNext();) {
306                 String JavaDoc key = it.next();
307                 String JavaDoc value = groups.get(key);
308                 if(value != null) {
309                     // XXX the same pattern everywhere when calling match()
310
value = value.trim();
311                     if(value != null && match(value, host)) {
312                         return svnServers.get(key);
313                     }
314                 }
315             }
316         }
317         return null;
318     }
319        
320     /**
321      * Evaluates if the given hostaname or IP address is in the given value String.
322      *
323      * @param value the value String. A list of host names or IP addresses delimited by ",".
324      * (e.g 192.168.0.1,*.168.0.1, some.domain.com, *.anything.com, ...)
325      * @param host the hostname or IP address
326      * @return true if the host name or IP address was found in the values String, otherwise false.
327      */

328     private boolean match(String JavaDoc value, String JavaDoc host) {
329         String JavaDoc[] values = value.split(","); // NOI18N
330
for (int i = 0; i < values.length; i++) {
331             value = values[i].trim();
332
333             if(value.equals("*") || value.equals(host) ) { // NOI18N
334
return true;
335             }
336
337             int idx = value.indexOf("*"); // NOI18N
338
if(idx > -1 && matchSegments(value, host) ) {
339                 return true;
340             }
341         }
342         return false;
343     }
344
345     /**
346      * Evaluates if the given hostaname or IP address matches with the given value String representing
347      * a hostaname or IP adress with one or more "*" wildcards in it.
348      *
349      * @param value the value String. A host name or IP addresse with a "*" wildcard. (e.g *.168.0.1 or *.anything.com)
350      * @param host the hostname or IP address
351      * @return true if the host name or IP address matches with the values String, otherwise false.
352      */

353     private boolean matchSegments(String JavaDoc value, String JavaDoc host) {
354         String JavaDoc[] valueSegments = value.split("."); // NOI18N
355
String JavaDoc[] hostSegments = host.split("."); // NOI18N
356

357         int idx = 0;
358         for (int i = 0; i < hostSegments.length; i++) {
359             if( !valueSegments[idx].equals("*") && // NOI18N
360
!valueSegments[idx].equals(hostSegments[i]) )
361             {
362                 return false;
363             }
364             if( !valueSegments[idx].equals("*") ) { // NOI18N
365
idx++;
366             }
367         }
368         return false;
369     }
370
371     /**
372      * Copies the given configuration file from the Subversion commandline client
373      * configuration directory into the configuration directory used by the Netbeans Subversion module. </br>
374      */

375     private Ini copyConfigFileToIDEConfigDir(String JavaDoc fileName, IniFilePatcher patcher) {
376         Ini systemIniFile = loadSystemIniFile(fileName);
377
378         patcher.patch(systemIniFile);
379
380         File JavaDoc file = FileUtil.normalizeFile(new File JavaDoc(getNBConfigPath() + "/" + fileName)); // NOI18N
381
try {
382             file.getParentFile().mkdirs();
383             systemIniFile.store(FileUtils.createOutputStream(file));
384         } catch (IOException JavaDoc ex) {
385             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); // should not happen
386
}
387         return systemIniFile;
388     }
389
390     /**
391      * Loads the ini configuration file from the directory used by
392      * the Subversion commandline client. The settings are loaded and merged together in
393      * in the folowing order:
394      * <ol>
395      * <li> The per-user INI files
396      * <li> The system-wide INI files
397      * </ol>
398      *
399      * @param fileName the file name
400      * @return an Ini instance holding the cofiguration file.
401      */

402     private Ini loadSystemIniFile(String JavaDoc fileName) {
403         // config files from userdir
404
String JavaDoc filePath = getUserConfigPath() + "/" + fileName; // NOI18N
405
File JavaDoc file = FileUtil.normalizeFile(new File JavaDoc(filePath));
406         Ini system = null;
407         try {
408             system = new Ini(new FileReader JavaDoc(file));
409         } catch (FileNotFoundException JavaDoc ex) {
410             system = new Ini();
411         } catch (IOException JavaDoc ex) {
412             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
413         }
414         
415         Ini global = null;
416         try {
417             global = new Ini(new FileReader JavaDoc(getGlobalConfigPath() + "/" + fileName)); // NOI18N
418
} catch (FileNotFoundException JavaDoc ex) {
419             // just doesn't exist - ignore
420
} catch (IOException JavaDoc ex) {
421             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
422         }
423                 
424         if(global != null) {
425             merge(global, system);
426         }
427
428         if(system.size() < 1) {
429             ErrorManager.getDefault().log(ErrorManager.WARNING, "Could not load the file " + filePath + ". Falling back on svn defaults."); // NOI18N
430
}
431         return system;
432     }
433
434     /**
435      * Merges only sections/keys/values into target which are not already present in source
436      *
437      * @param source the source ini file
438      * @param target the target ini file in which the values from the source file are going to be merged
439      */

440     private void merge(Ini source, Ini target) {
441         for (Iterator JavaDoc<String JavaDoc> itSections = source.keySet().iterator(); itSections.hasNext();) {
442             String JavaDoc sectionName = itSections.next();
443             Ini.Section sourceSection = source.get( sectionName );
444             Ini.Section targetSection = target.get( sectionName );
445
446             if(targetSection == null) {
447                 targetSection = target.add(sectionName);
448             }
449
450             for (Iterator JavaDoc<String JavaDoc> itVariables = sourceSection.keySet().iterator(); itVariables.hasNext();) {
451                 String JavaDoc key = itVariables.next();
452
453                 if(!targetSection.containsKey(key)) {
454                     targetSection.put(key, sourceSection.get(key));
455                 }
456             }
457         }
458     }
459    
460     /**
461      * Evaluates if the value stored under the key is a proxy setting value.
462      *
463      * @param key the key
464      * @return true if the value stored under the key is a proxy setting value. Otherwise false
465      */

466     private boolean isProxyConfigurationKey(String JavaDoc key) {
467         return key.equals("http-proxy-host") || // NOI18N
468
key.equals("http-proxy-port") || // NOI18N
469
key.equals("http-proxy-username") || // NOI18N
470
key.equals("http-proxy-password"); // NOI18N
471
}
472     
473     /**
474      * Return the path for the systemwide command lines configuration directory
475      */

476     private static String JavaDoc getGlobalConfigPath () {
477         if(Utilities.isUnix()) {
478             return "/etc/subversion"; // NOI18N
479
} else if (Utilities.isWindows()){
480             return WINDOWS_GLOBAL_CONFIG_DIR;
481         }
482         return ""; // NOI18N
483
}
484
485     /**
486      * Returns the value for the %APPDATA% env variable on windows
487      *
488      */

489     private static String JavaDoc getAPPDATA() {
490         String JavaDoc appdata = "";
491         if(Utilities.isWindows()) {
492             appdata = System.getenv("APPDATA");// NOI18N
493
}
494         return appdata!= null? appdata: "";
495     }
496
497     /**
498      * Returns the value for the %ALLUSERSPROFILE% + the last foder segment from %APPDATA% env variables on windows
499      *
500      */

501     private static String JavaDoc getGlobalAPPDATA() {
502         if(Utilities.isWindows()) {
503             String JavaDoc globalProfile = System.getenv("ALLUSERSPROFILE"); // NOI18N
504
if(globalProfile == null || globalProfile.trim().equals("")) { // NOI18N
505
globalProfile = "";
506             }
507             String JavaDoc appdataPath = WINDOWS_USER_APPDATA;
508             if(appdataPath == null || appdataPath.equals("")) { // NOI18N
509
return ""; // NOI18N
510
}
511             String JavaDoc appdata = ""; // NOI18N
512
int idx = appdataPath.lastIndexOf("\\"); // NOI18N
513
if(idx > -1) {
514                 appdata = appdataPath.substring(idx + 1);
515                 if(appdata.trim().equals("")) { // NOI18N
516
int previdx = appdataPath.lastIndexOf("\\", idx); // NOI18N
517
if(idx > -1) {
518                         appdata = appdataPath.substring(previdx + 1, idx);
519                     }
520                 }
521             } else {
522                 return ""; // NOI18N
523
}
524             return globalProfile + "/" + appdata; // NOI18N
525
}
526         return ""; // NOI18N
527
}
528         
529 }
530
Popular Tags