comparison src/org/tmatesoft/hg/internal/ConfigFile.java @ 378:9fb990c8a724

Investigate approaches to alter Mercurial configuration files
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 09 Feb 2012 04:15:17 +0100
parents a37ce7145c3f
children e31e85cf4d4c
comparison
equal deleted inserted replaced
377:86f049e6bcae 378:9fb990c8a724
15 * contact TMate Software at support@hg4j.com 15 * contact TMate Software at support@hg4j.com
16 */ 16 */
17 package org.tmatesoft.hg.internal; 17 package org.tmatesoft.hg.internal;
18 18
19 import java.io.BufferedReader; 19 import java.io.BufferedReader;
20 import java.io.ByteArrayOutputStream;
20 import java.io.File; 21 import java.io.File;
22 import java.io.FileOutputStream;
21 import java.io.FileReader; 23 import java.io.FileReader;
22 import java.io.IOException; 24 import java.io.IOException;
25 import java.io.PrintStream;
26 import java.nio.ByteBuffer;
27 import java.nio.channels.FileChannel;
28 import java.nio.channels.FileLock;
23 import java.util.ArrayList; 29 import java.util.ArrayList;
24 import java.util.Collections; 30 import java.util.Collections;
31 import java.util.Iterator;
25 import java.util.LinkedHashMap; 32 import java.util.LinkedHashMap;
26 import java.util.List; 33 import java.util.List;
27 import java.util.Map; 34 import java.util.Map;
28 35
29 /** 36 /**
50 public List<String> getSectionNames() { 57 public List<String> getSectionNames() {
51 return sections == null ? Collections.<String>emptyList() : Collections.unmodifiableList(sections); 58 return sections == null ? Collections.<String>emptyList() : Collections.unmodifiableList(sections);
52 } 59 }
53 60
54 public Map<String,String> getSection(String sectionName) { 61 public Map<String,String> getSection(String sectionName) {
55 if (sections == null) { 62 if (sections == null) {
56 return Collections.emptyMap(); 63 return Collections.emptyMap();
57 } 64 }
58 int x = sections.indexOf(sectionName); 65 int x = sections.indexOf(sectionName);
59 if (x == -1) { 66 if (x == -1) {
60 return Collections.emptyMap(); 67 return Collections.emptyMap();
77 84
78 public String getString(String sectionName, String key, String defaultValue) { 85 public String getString(String sectionName, String key, String defaultValue) {
79 String value = getSection(sectionName).get(key); 86 String value = getSection(sectionName).get(key);
80 return value == null ? defaultValue : value; 87 return value == null ? defaultValue : value;
81 } 88 }
82 89
90 public void putString(String sectionName, String key, String newValue) {
91 Map<String, String> section = null;
92 if (sections == null) {
93 // init, in case we didn't read any file with prev config
94 sections = new ArrayList<String>();
95 content = new ArrayList<Map<String,String>>();
96 }
97 int x = sections.indexOf(sectionName);
98 if (x == -1) {
99 if (newValue == null) {
100 return;
101 }
102 sections.add(sectionName);
103 content.add(section = new LinkedHashMap<String, String>());
104 } else {
105 section = content.get(x);
106 }
107 if (newValue == null) {
108 section.remove(key);
109 } else {
110 section.put(key, newValue);
111 }
112 }
113
83 // TODO handle %include and %unset directives 114 // TODO handle %include and %unset directives
84 // TODO "" and lists 115 // TODO "" and lists
85 // XXX perhaps, single string to keep whole section with substrings for keys/values to minimize number of arrays (String.value) 116 // XXX perhaps, single string to keep whole section with substrings for keys/values to minimize number of arrays (String.value)
86 private void read(File f) throws IOException { 117 private void read(File f) throws IOException {
87 if (f == null || !f.canRead()) { 118 if (f == null || !f.canRead()) {
139 br.close(); 170 br.close();
140 } 171 }
141 } 172 }
142 assert sections.size() == content.size(); 173 assert sections.size() == content.size();
143 } 174 }
175
176 public void writeTo(File f) throws IOException {
177 byte[] data = compose();
178 if (!f.exists()) {
179 f.createNewFile();
180 }
181 FileChannel fc = new FileOutputStream(f).getChannel();
182 FileLock fl = fc.lock();
183 try {
184 fc.write(ByteBuffer.wrap(data));
185 } finally {
186 fl.release();
187 fc.close();
188 }
189 }
190
191 private byte[] compose() {
192 ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
193 PrintStream ps = new PrintStream(bos);
194 Iterator<String> sectionNames = sections.iterator();
195 for (Map<String,String> s : content) {
196 final String name = sectionNames.next(); // iterate through names despite section may be empty
197 if (s.isEmpty()) {
198 continue; // do not write an empty section
199 }
200 ps.print('[');
201 ps.print(name);
202 ps.println(']');
203 for (Map.Entry<String, String> e : s.entrySet()) {
204 ps.print(e.getKey());
205 ps.print('=');
206 ps.println(e.getValue());
207 }
208 ps.println();
209 }
210 ps.flush();
211 return bos.toByteArray();
212 }
144 } 213 }