Coverage Report - org.ini4j.addon.ConfigParser
 
Classes in this File Line Coverage Branch Coverage Complexity
ConfigParser
100%
95/95
98%
41/42
0
ConfigParser$1
N/A
N/A
0
ConfigParser$ConfigParserException
100%
2/2
N/A
0
ConfigParser$DuplicateSectionException
100%
3/3
N/A
0
ConfigParser$InterpolationException
100%
2/2
N/A
0
ConfigParser$InterpolationMissingOptionException
100%
3/3
N/A
0
ConfigParser$NoOptionException
100%
3/3
N/A
0
ConfigParser$NoSectionException
100%
3/3
N/A
0
ConfigParser$ParsingException
100%
3/3
N/A
0
ConfigParser$PyIni
98%
54/55
92%
24/26
0
 
 1  
 /*
 2  
  * Copyright 2005,2009 Ivan SZKIBA
 3  
  *
 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
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 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.
 15  
  */
 16  
 package org.ini4j.addon;
 17  
 
 18  
 import org.ini4j.Config;
 19  
 import org.ini4j.Ini;
 20  
 import org.ini4j.IniHandler;
 21  
 import org.ini4j.InvalidIniFormatException;
 22  
 
 23  
 import org.ini4j.spi.Warnings;
 24  
 
 25  
 import java.io.File;
 26  
 import java.io.FileReader;
 27  
 import java.io.FileWriter;
 28  
 import java.io.IOException;
 29  
 import java.io.InputStream;
 30  
 import java.io.OutputStream;
 31  
 import java.io.Reader;
 32  
 import java.io.Writer;
 33  
 
 34  
 import java.net.URL;
 35  
 
 36  
 import java.util.ArrayList;
 37  
 import java.util.Collections;
 38  
 import java.util.HashMap;
 39  
 import java.util.List;
 40  
 import java.util.Map;
 41  
 import java.util.regex.Matcher;
 42  
 import java.util.regex.Pattern;
 43  
 
 44  
 public class ConfigParser
 45  
 {
 46  
     private PyIni _ini;
 47  
 
 48  
     @SuppressWarnings(Warnings.UNCHECKED)
 49  
     public ConfigParser()
 50  
     {
 51  24
         this(Collections.EMPTY_MAP);
 52  24
     }
 53  
 
 54  
     public ConfigParser(Map<String, String> defaults)
 55  29
     {
 56  29
         _ini = new PyIni(defaults);
 57  29
     }
 58  
 
 59  
     public boolean getBoolean(String section, String option) throws NoSectionException, NoOptionException, InterpolationException
 60  
     {
 61  
         boolean ret;
 62  11
         String value = get(section, option);
 63  
 
 64  11
         if ("1".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value) || "on".equalsIgnoreCase(value))
 65  
         {
 66  5
             ret = true;
 67  
         }
 68  6
         else if ("0".equalsIgnoreCase(value) || "no".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value) || "off".equalsIgnoreCase(value))
 69  
         {
 70  5
             ret = false;
 71  
         }
 72  
         else
 73  
         {
 74  1
             throw new IllegalArgumentException(value);
 75  
         }
 76  
 
 77  10
         return ret;
 78  
     }
 79  
 
 80  
     public double getDouble(String section, String option) throws NoSectionException, NoOptionException, InterpolationException
 81  
     {
 82  1
         return Double.parseDouble(get(section, option));
 83  
     }
 84  
 
 85  
     public float getFloat(String section, String option) throws NoSectionException, NoOptionException, InterpolationException
 86  
     {
 87  1
         return Float.parseFloat(get(section, option));
 88  
     }
 89  
 
 90  
     public int getInt(String section, String option) throws NoSectionException, NoOptionException, InterpolationException
 91  
     {
 92  1
         return Integer.parseInt(get(section, option));
 93  
     }
 94  
 
 95  
     public long getLong(String section, String option) throws NoSectionException, NoOptionException, InterpolationException
 96  
     {
 97  1
         return Long.parseLong(get(section, option));
 98  
     }
 99  
 
 100  
     public void addSection(String section) throws DuplicateSectionException
 101  
     {
 102  20
         if (_ini.containsKey(section))
 103  
         {
 104  1
             throw new DuplicateSectionException(section);
 105  
         }
 106  19
         else if (PyIni.DEFAULT_SECTION_NAME.equalsIgnoreCase(section))
 107  
         {
 108  1
             throw new IllegalArgumentException(section);
 109  
         }
 110  
 
 111  18
         _ini.add(section);
 112  18
     }
 113  
 
 114  
     public Map<String, String> defaults()
 115  
     {
 116  4
         return _ini.getDefaults();
 117  
     }
 118  
 
 119  
     @SuppressWarnings(Warnings.UNCHECKED)
 120  
     public String get(String section, String option) throws NoSectionException, NoOptionException, InterpolationException
 121  
     {
 122  64
         return get(section, option, false, Collections.EMPTY_MAP);
 123  
     }
 124  
 
 125  
     @SuppressWarnings(Warnings.UNCHECKED)
 126  
     public String get(String section, String option, boolean raw) throws NoSectionException, NoOptionException, InterpolationException
 127  
     {
 128  1
         return get(section, option, raw, Collections.EMPTY_MAP);
 129  
     }
 130  
 
 131  
     public String get(String sectionName, String optionName, boolean raw, Map<String, String> variables) throws NoSectionException, NoOptionException,
 132  
         InterpolationException
 133  
     {
 134  66
         String value = requireOption(sectionName, optionName);
 135  
 
 136  64
         if (!raw && (value != null) && (value.indexOf(PyIni.SUBST_CHAR) >= 0))
 137  
         {
 138  17
             value = _ini.fetch(sectionName, optionName, variables);
 139  
         }
 140  
 
 141  60
         return value;
 142  
     }
 143  
 
 144  
     public boolean hasOption(String sectionName, String optionName)
 145  
     {
 146  5
         Ini.Section section = _ini.get(sectionName);
 147  
 
 148  5
         return (section != null) && section.containsKey(optionName);
 149  
     }
 150  
 
 151  
     public boolean hasSection(String sectionName)
 152  
     {
 153  3
         return _ini.containsKey(sectionName);
 154  
     }
 155  
 
 156  
     @SuppressWarnings(Warnings.UNCHECKED)
 157  
     public List<Map.Entry<String, String>> items(String sectionName) throws NoSectionException, InterpolationMissingOptionException
 158  
     {
 159  1
         return items(sectionName, false, Collections.EMPTY_MAP);
 160  
     }
 161  
 
 162  
     @SuppressWarnings(Warnings.UNCHECKED)
 163  
     public List<Map.Entry<String, String>> items(String sectionName, boolean raw) throws NoSectionException, InterpolationMissingOptionException
 164  
     {
 165  1
         return items(sectionName, raw, Collections.EMPTY_MAP);
 166  
     }
 167  
 
 168  
     public List<Map.Entry<String, String>> items(String sectionName, boolean raw, Map<String, String> variables) throws NoSectionException,
 169  
         InterpolationMissingOptionException
 170  
     {
 171  2
         Ini.Section section = requireSection(sectionName);
 172  
         Map<String, String> ret;
 173  
 
 174  2
         if (raw)
 175  
         {
 176  1
             ret = new HashMap<String, String>(section);
 177  
         }
 178  
         else
 179  
         {
 180  1
             ret = new HashMap<String, String>();
 181  1
             for (String key : section.keySet())
 182  
             {
 183  5
                 ret.put(key, _ini.fetch(section, key, variables));
 184  
             }
 185  
         }
 186  
 
 187  2
         return new ArrayList<Map.Entry<String, String>>(ret.entrySet());
 188  
     }
 189  
 
 190  
     public List<String> options(String sectionName) throws NoSectionException
 191  
     {
 192  3
         requireSection(sectionName);
 193  
 
 194  3
         return new ArrayList<String>(_ini.get(sectionName).keySet());
 195  
     }
 196  
 
 197  
     public void read(String... filenames) throws IOException, ParsingException
 198  
     {
 199  4
         for (String filename : filenames)
 200  
         {
 201  2
             read(new File(filename));
 202  
         }
 203  2
     }
 204  
 
 205  
     public void read(Reader reader) throws IOException, ParsingException
 206  
     {
 207  
         try
 208  
         {
 209  2
             _ini.load(reader);
 210  
         }
 211  1
         catch (InvalidIniFormatException x)
 212  
         {
 213  1
             throw new ParsingException(x);
 214  1
         }
 215  1
     }
 216  
 
 217  
     public void read(URL url) throws IOException, ParsingException
 218  
     {
 219  
         try
 220  
         {
 221  2
             _ini.load(url);
 222  
         }
 223  1
         catch (InvalidIniFormatException x)
 224  
         {
 225  1
             throw new ParsingException(x);
 226  1
         }
 227  1
     }
 228  
 
 229  
     public void read(File file) throws IOException, ParsingException
 230  
     {
 231  
         try
 232  
         {
 233  10
             _ini.load(new FileReader(file));
 234  
         }
 235  1
         catch (InvalidIniFormatException x)
 236  
         {
 237  1
             throw new ParsingException(x);
 238  9
         }
 239  9
     }
 240  
 
 241  
     public void read(InputStream stream) throws IOException, ParsingException
 242  
     {
 243  
         try
 244  
         {
 245  2
             _ini.load(stream);
 246  
         }
 247  1
         catch (InvalidIniFormatException x)
 248  
         {
 249  1
             throw new ParsingException(x);
 250  1
         }
 251  1
     }
 252  
 
 253  
     public boolean removeOption(String sectionName, String optionName) throws NoSectionException
 254  
     {
 255  1
         Ini.Section section = requireSection(sectionName);
 256  1
         boolean ret = section.containsKey(optionName);
 257  
 
 258  1
         section.remove(optionName);
 259  
 
 260  1
         return ret;
 261  
     }
 262  
 
 263  
     public boolean removeSection(String sectionName)
 264  
     {
 265  1
         boolean ret = _ini.containsKey(sectionName);
 266  
 
 267  1
         _ini.remove(sectionName);
 268  
 
 269  1
         return ret;
 270  
     }
 271  
 
 272  
     public List<String> sections()
 273  
     {
 274  11
         return new ArrayList<String>(_ini.keySet());
 275  
     }
 276  
 
 277  
     public void set(String sectionName, String optionName, Object value) throws NoSectionException
 278  
     {
 279  17
         Ini.Section section = requireSection(sectionName);
 280  
 
 281  16
         if (value == null)
 282  
         {
 283  1
             section.remove(optionName);
 284  
         }
 285  
         else
 286  
         {
 287  15
             section.put(optionName, value.toString());
 288  
         }
 289  16
     }
 290  
 
 291  
     public void write(Writer writer) throws IOException
 292  
     {
 293  1
         _ini.store(writer);
 294  1
     }
 295  
 
 296  
     public void write(OutputStream stream) throws IOException
 297  
     {
 298  1
         _ini.store(stream);
 299  1
     }
 300  
 
 301  
     public void write(File file) throws IOException
 302  
     {
 303  1
         _ini.store(new FileWriter(file));
 304  1
     }
 305  
 
 306  
     protected PyIni getIni()
 307  
     {
 308  58
         return _ini;
 309  
     }
 310  
 
 311  
     private String requireOption(String sectionName, String optionName) throws NoSectionException, NoOptionException
 312  
     {
 313  66
         Ini.Section section = requireSection(sectionName);
 314  65
         String option = section.get(optionName);
 315  
 
 316  65
         if (option == null)
 317  
         {
 318  1
             throw new NoOptionException(optionName);
 319  
         }
 320  
 
 321  64
         return option;
 322  
     }
 323  
 
 324  
     private Ini.Section requireSection(String sectionName) throws NoSectionException
 325  
     {
 326  89
         Ini.Section section = _ini.get(sectionName);
 327  
 
 328  89
         if (section == null)
 329  
         {
 330  2
             throw new NoSectionException(sectionName);
 331  
         }
 332  
 
 333  87
         return section;
 334  
     }
 335  
 
 336  
     public static class ConfigParserException extends Exception
 337  
     {
 338  
 
 339  
         /** Use serialVersionUID for interoperability. */ private static final long serialVersionUID = -6845546313519392093L;
 340  
 
 341  
         public ConfigParserException(String message)
 342  
         {
 343  8
             super(message);
 344  8
         }
 345  
     }
 346  
 
 347  1
     public static final class DuplicateSectionException extends ConfigParserException
 348  
     {
 349  
 
 350  
         /** Use serialVersionUID for interoperability. */ private static final long serialVersionUID = -5244008445735700699L;
 351  
 
 352  
         private DuplicateSectionException(String message)
 353  
         {
 354  1
             super(message);
 355  1
         }
 356  
     }
 357  
 
 358  
     public static class InterpolationException extends ConfigParserException
 359  
     {
 360  
 
 361  
         /** Use serialVersionUID for interoperability. */ private static final long serialVersionUID = 8924443303158546939L;
 362  
 
 363  
         protected InterpolationException(String message)
 364  
         {
 365  4
             super(message);
 366  4
         }
 367  
     }
 368  
 
 369  4
     public static final class InterpolationMissingOptionException extends InterpolationException
 370  
     {
 371  
 
 372  
         /** Use serialVersionUID for interoperability. */ private static final long serialVersionUID = 2903136975820447879L;
 373  
 
 374  
         private InterpolationMissingOptionException(String message)
 375  
         {
 376  4
             super(message);
 377  4
         }
 378  
     }
 379  
 
 380  1
     public static final class NoOptionException extends ConfigParserException
 381  
     {
 382  
 
 383  
         /** Use serialVersionUID for interoperability. */ private static final long serialVersionUID = 8460082078809425858L;
 384  
 
 385  
         private NoOptionException(String message)
 386  
         {
 387  1
             super(message);
 388  1
         }
 389  
     }
 390  
 
 391  2
     public static final class NoSectionException extends ConfigParserException
 392  
     {
 393  
 
 394  
         /** Use serialVersionUID for interoperability. */ private static final long serialVersionUID = 8553627727493146118L;
 395  
 
 396  
         private NoSectionException(String message)
 397  
         {
 398  2
             super(message);
 399  2
         }
 400  
     }
 401  
 
 402  4
     public static final class ParsingException extends IOException
 403  
     {
 404  
 
 405  
         /** Use serialVersionUID for interoperability. */ private static final long serialVersionUID = -5395990242007205038L;
 406  
 
 407  
         private ParsingException(Throwable cause)
 408  
         {
 409  4
             super(cause.getMessage(), cause);
 410  4
         }
 411  
     }
 412  
 
 413  
     protected static class PyIni extends Ini
 414  
     {
 415  
         private static final char SUBST_CHAR = '%';
 416  1
         private static final Pattern EXPRESSION = Pattern.compile("(?<!\\\\)\\%\\(([^\\)]+)\\)");
 417  
         private static final int G_OPTION = 1;
 418  
         protected static final String DEFAULT_SECTION_NAME = "DEFAULT";
 419  
         private final Map<String, String> _defaults;
 420  
         private Ini.Section _defaultSection;
 421  
 
 422  
         public PyIni(Map<String, String> defaults)
 423  29
         {
 424  29
             _defaults = defaults;
 425  29
             Config cfg = getConfig().clone();
 426  
 
 427  29
             cfg.setEscape(false);
 428  29
             cfg.setMultiOption(false);
 429  29
             cfg.setMultiSection(false);
 430  29
             cfg.setLowerCaseOption(true);
 431  29
             cfg.setLowerCaseSection(true);
 432  29
             super.setConfig(cfg);
 433  29
         }
 434  
 
 435  
         @Override public void setConfig(Config value)
 436  
         {
 437  
             assert true;
 438  0
         }
 439  
 
 440  
         public Map<String, String> getDefaults()
 441  
         {
 442  4
             return _defaults;
 443  
         }
 444  
 
 445  
         @Override public Section add(String name)
 446  
         {
 447  
             Section section;
 448  
 
 449  90
             if (DEFAULT_SECTION_NAME.equalsIgnoreCase(name))
 450  
             {
 451  13
                 if (_defaultSection == null)
 452  
                 {
 453  9
                     _defaultSection = new Ini.Section(name);
 454  
                 }
 455  
 
 456  13
                 section = _defaultSection;
 457  
             }
 458  
             else
 459  
             {
 460  77
                 section = super.add(name);
 461  
             }
 462  
 
 463  90
             return section;
 464  
         }
 465  
 
 466  
         public String fetch(String sectionName, String optionName, Map<String, String> variables) throws InterpolationMissingOptionException
 467  
         {
 468  17
             return fetch(get(sectionName), optionName, variables);
 469  
         }
 470  
 
 471  
         protected Ini.Section getDefaultSection()
 472  
         {
 473  8
             return _defaultSection;
 474  
         }
 475  
 
 476  
         protected String fetch(Ini.Section section, String optionName, Map<String, String> variables) throws InterpolationMissingOptionException
 477  
         {
 478  22
             String value = section.get(optionName);
 479  
 
 480  22
             if ((value != null) && (value.indexOf(SUBST_CHAR) >= 0))
 481  
             {
 482  19
                 StringBuilder buffer = new StringBuilder(value);
 483  
 
 484  19
                 resolve(buffer, section, variables);
 485  15
                 value = buffer.toString();
 486  
             }
 487  
 
 488  18
             return value;
 489  
         }
 490  
 
 491  
         protected void resolve(StringBuilder buffer, Ini.Section owner, Map<String, String> vars) throws InterpolationMissingOptionException
 492  
         {
 493  19
             Matcher m = EXPRESSION.matcher(buffer);
 494  
 
 495  34
             while (m.find())
 496  
             {
 497  19
                 String optionName = m.group(G_OPTION);
 498  19
                 String value = owner.get(optionName);
 499  
 
 500  19
                 if (value == null)
 501  
                 {
 502  15
                     value = vars.get(optionName);
 503  
                 }
 504  
 
 505  19
                 if (value == null)
 506  
                 {
 507  14
                     value = _defaults.get(optionName);
 508  
                 }
 509  
 
 510  19
                 if ((value == null) && (_defaultSection != null))
 511  
                 {
 512  10
                     value = _defaultSection.get(optionName);
 513  
                 }
 514  
 
 515  19
                 if (value == null)
 516  
                 {
 517  4
                     throw new InterpolationMissingOptionException(optionName);
 518  
                 }
 519  
 
 520  15
                 buffer.replace(m.start(), m.end(), value);
 521  15
                 m.reset(buffer);
 522  15
             }
 523  15
         }
 524  
 
 525  
         @Override protected void store(IniHandler formatter) throws IOException
 526  
         {
 527  3
             formatter.startIni();
 528  3
             if (_defaultSection != null)
 529  
             {
 530  3
                 store(formatter, _defaultSection);
 531  
             }
 532  
 
 533  3
             for (Ini.Section s : values())
 534  
             {
 535  21
                 store(formatter, s);
 536  
             }
 537  
 
 538  3
             formatter.endIni();
 539  3
         }
 540  
 
 541  
         protected void store(IniHandler formatter, Section section) throws IOException
 542  
         {
 543  24
             formatter.startSection(section.getName());
 544  24
             for (String name : section.keySet())
 545  
             {
 546  120
                 formatter.handleOption(name, section.get(name));
 547  
             }
 548  
 
 549  24
             formatter.endSection();
 550  24
         }
 551  
     }
 552  
 }