1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| |
8 |
| |
9 |
| |
10 |
| |
11 |
| |
12 |
| |
13 |
| |
14 |
| |
15 |
| |
16 |
| |
17 |
| package org.ini4j.addon; |
18 |
| |
19 |
| import java.io.IOException; |
20 |
| import java.io.LineNumberReader; |
21 |
| import java.io.Reader; |
22 |
| import java.io.InputStreamReader; |
23 |
| import java.net.URL; |
24 |
| import java.util.*; |
25 |
| import org.ini4j.*; |
26 |
| |
27 |
| public class FancyIniParser extends IniParser |
28 |
| { |
29 |
| public static final char INCLUDE_BEGIN = '<'; |
30 |
| public static final char INCLUDE_END = '>'; |
31 |
| |
32 |
| private boolean _allowEmptyOption = true; |
33 |
| private boolean _allowUnnamedSection = true; |
34 |
| private boolean _allowMissingSection = true; |
35 |
| private String _missingSectionName = ""; |
36 |
| private boolean _allowSectionCaseConversion; |
37 |
| private boolean _allowOptionCaseConversion; |
38 |
| private boolean _allowInclude = true; |
39 |
| |
40 |
1
| public synchronized void setAllowEmptyOption(boolean flag)
|
41 |
| { |
42 |
1
| _allowEmptyOption = flag;
|
43 |
| } |
44 |
| |
45 |
2
| public synchronized boolean isAllowEmptyOption()
|
46 |
| { |
47 |
2
| return _allowEmptyOption;
|
48 |
| } |
49 |
| |
50 |
1
| public synchronized void setAllowUnnamedSection(boolean flag)
|
51 |
| { |
52 |
1
| _allowUnnamedSection = flag;
|
53 |
| } |
54 |
| |
55 |
2
| public synchronized boolean isAllowUnnamedSection()
|
56 |
| { |
57 |
2
| return _allowUnnamedSection;
|
58 |
| } |
59 |
| |
60 |
1
| public synchronized void setAllowMissingSection(boolean flag)
|
61 |
| { |
62 |
1
| _allowMissingSection = flag;
|
63 |
| } |
64 |
| |
65 |
3
| public synchronized boolean isAllowMissingSection()
|
66 |
| { |
67 |
3
| return _allowMissingSection;
|
68 |
| } |
69 |
| |
70 |
1
| public synchronized void setMissingSectionName(String name)
|
71 |
| { |
72 |
1
| _missingSectionName = name;
|
73 |
| } |
74 |
| |
75 |
3
| public synchronized String getMissingSectionName()
|
76 |
| { |
77 |
3
| return _missingSectionName;
|
78 |
| } |
79 |
| |
80 |
1
| public synchronized void setAllowSectionCaseConversion(boolean flag)
|
81 |
| { |
82 |
1
| _allowSectionCaseConversion = flag;
|
83 |
| } |
84 |
| |
85 |
25
| public synchronized boolean isAllowSectionCaseConversion()
|
86 |
| { |
87 |
25
| return _allowSectionCaseConversion;
|
88 |
| } |
89 |
| |
90 |
1
| public synchronized void setAllowOptionCaseConversion(boolean flag)
|
91 |
| { |
92 |
1
| _allowOptionCaseConversion = flag;
|
93 |
| } |
94 |
| |
95 |
73
| public synchronized boolean isAllowOptionCaseConversion()
|
96 |
| { |
97 |
73
| return _allowOptionCaseConversion;
|
98 |
| } |
99 |
| |
100 |
2
| public synchronized boolean isAllowInclude()
|
101 |
| { |
102 |
2
| return _allowInclude;
|
103 |
| } |
104 |
| |
105 |
1
| public synchronized void setAllowInclude(boolean flag)
|
106 |
| { |
107 |
1
| _allowInclude = flag;
|
108 |
| } |
109 |
| |
110 |
| protected static class IniSource |
111 |
| { |
112 |
| protected URL base; |
113 |
| protected Stack<URL> bases; |
114 |
| |
115 |
| protected LineNumberReader reader; |
116 |
| protected Stack<LineNumberReader> readers; |
117 |
| |
118 |
13
| protected IniSource(Reader input)
|
119 |
| { |
120 |
13
| reader = new LineNumberReader(input);
|
121 |
| } |
122 |
| |
123 |
2
| protected IniSource(URL base) throws IOException
|
124 |
| { |
125 |
2
| this.base = base;
|
126 |
2
| reader = new LineNumberReader(new InputStreamReader(base.openStream()));
|
127 |
| } |
128 |
| |
129 |
5
| protected void include(LineNumberReader input, URL location)
|
130 |
| { |
131 |
5
| if ( readers == null )
|
132 |
| { |
133 |
2
| readers = new Stack<LineNumberReader>();
|
134 |
2
| bases = new Stack<URL>();
|
135 |
| } |
136 |
| |
137 |
5
| readers.push(reader);
|
138 |
5
| bases.push(base);
|
139 |
| |
140 |
5
| reader = input;
|
141 |
5
| base = location;
|
142 |
| } |
143 |
| |
144 |
5
| protected int getLineNumber()
|
145 |
| { |
146 |
5
| return reader.getLineNumber();
|
147 |
| } |
148 |
| |
149 |
165
| protected String readLine() throws IOException
|
150 |
| { |
151 |
165
| String line = reader.readLine();
|
152 |
| |
153 |
165
| if ( line == null )
|
154 |
| { |
155 |
14
| if ( (readers != null) && ! readers.empty() )
|
156 |
| { |
157 |
5
| reader = readers.pop();
|
158 |
5
| base = bases.pop();
|
159 |
5
| line = readLine();
|
160 |
| } |
161 |
| } |
162 |
| else |
163 |
| { |
164 |
151
| String buff = line.trim();
|
165 |
| |
166 |
151
| if ( (buff.length() > 2) && (buff.charAt(0) == INCLUDE_BEGIN) && (buff.charAt(buff.length() - 1) == INCLUDE_END) )
|
167 |
| { |
168 |
6
| buff = buff.substring(1, buff.length()-1).trim();
|
169 |
| |
170 |
6
| URL loc = base == null ? new URL(buff) : new URL(base, buff);
|
171 |
| |
172 |
5
| LineNumberReader inc = new LineNumberReader(new InputStreamReader(loc.openStream()));
|
173 |
5
| include(inc, loc);
|
174 |
5
| line = readLine();
|
175 |
| } |
176 |
| } |
177 |
| |
178 |
164
| return line;
|
179 |
| } |
180 |
| } |
181 |
| |
182 |
13
| public void parse(Reader input, IniHandler handler) throws IOException, InvalidIniFormatException
|
183 |
| { |
184 |
13
| parse(new IniSource(input), handler);
|
185 |
| } |
186 |
| |
187 |
2
| public void parse(URL input, IniHandler handler) throws IOException, InvalidIniFormatException
|
188 |
| { |
189 |
2
| parse(new IniSource(input), handler);
|
190 |
| } |
191 |
| |
192 |
15
| protected void parse(IniSource source, IniHandler handler) throws IOException, InvalidIniFormatException
|
193 |
| { |
194 |
15
| handler.startIni();
|
195 |
| |
196 |
15
| String sectionName = null;
|
197 |
| |
198 |
15
| for (String line = source.readLine(); line != null; line = source.readLine())
|
199 |
| { |
200 |
145
| line = line.trim();
|
201 |
| |
202 |
145
| if ( (line.length() == 0) || (COMMENTS.indexOf(line.charAt(0)) >= 0))
|
203 |
| { |
204 |
42
| continue;
|
205 |
| } |
206 |
| |
207 |
103
| if ( line.charAt(0) == SECTION_BEGIN )
|
208 |
| { |
209 |
27
| if ( sectionName != null )
|
210 |
| { |
211 |
17
| handler.endSection();
|
212 |
| } |
213 |
| |
214 |
27
| if ( line.charAt(line.length()-1) != SECTION_END )
|
215 |
| { |
216 |
1
| parseError(line, source.getLineNumber());
|
217 |
| } |
218 |
| |
219 |
26
| sectionName = unescape(line.substring(1, line.length()-1).trim());
|
220 |
| |
221 |
26
| if ( (sectionName.length() == 0) && ! isAllowUnnamedSection() )
|
222 |
| { |
223 |
1
| parseError(line, source.getLineNumber());
|
224 |
| } |
225 |
| |
226 |
25
| if ( isAllowSectionCaseConversion() )
|
227 |
| { |
228 |
1
| sectionName = sectionName.toLowerCase(Locale.getDefault());
|
229 |
| } |
230 |
| |
231 |
25
| handler.startSection(sectionName);
|
232 |
| } |
233 |
| else |
234 |
| { |
235 |
76
| if ( sectionName == null )
|
236 |
| { |
237 |
3
| if ( isAllowMissingSection() )
|
238 |
| { |
239 |
2
| sectionName = getMissingSectionName();
|
240 |
2
| handler.startSection(sectionName);
|
241 |
| } |
242 |
| else |
243 |
| { |
244 |
1
| parseError(line, source.getLineNumber());
|
245 |
| } |
246 |
| } |
247 |
| |
248 |
75
| int idx = line.indexOf(OPERATOR);
|
249 |
| |
250 |
75
| String name = null;
|
251 |
75
| String value = null;
|
252 |
| |
253 |
75
| if ( idx < 0 )
|
254 |
| { |
255 |
2
| if ( isAllowEmptyOption() )
|
256 |
| { |
257 |
1
| name = line;
|
258 |
| } |
259 |
| else |
260 |
| { |
261 |
1
| parseError(line, source.getLineNumber());
|
262 |
| } |
263 |
| } |
264 |
| else |
265 |
| { |
266 |
73
| name = unescape(line.substring(0, idx)).trim();
|
267 |
73
| value = unescape(line.substring(idx+1)).trim();
|
268 |
| } |
269 |
| |
270 |
74
| if ( name.length() == 0)
|
271 |
| { |
272 |
1
| parseError(line, source.getLineNumber());
|
273 |
| } |
274 |
| |
275 |
73
| if ( isAllowOptionCaseConversion() )
|
276 |
| { |
277 |
1
| name = name.toLowerCase(Locale.getDefault());
|
278 |
| } |
279 |
| |
280 |
73
| handler.handleOption(name, value);
|
281 |
| } |
282 |
| } |
283 |
| |
284 |
9
| if ( sectionName != null )
|
285 |
| { |
286 |
8
| handler.endSection();
|
287 |
| } |
288 |
| |
289 |
9
| handler.endIni();
|
290 |
| } |
291 |
| } |