1 16 17 package org.apache.commons.configuration; 18 19 import java.io.File ; 20 import java.io.FilterWriter ; 21 import java.io.IOException ; 22 import java.io.LineNumberReader ; 23 import java.io.Reader ; 24 import java.io.Writer ; 25 import java.io.StringReader ; 26 import java.io.BufferedReader ; 27 import java.net.URL ; 28 import java.util.Date ; 29 import java.util.Iterator ; 30 import java.util.List ; 31 32 import org.apache.commons.lang.StringEscapeUtils; 33 import org.apache.commons.lang.StringUtils; 34 35 135 public class PropertiesConfiguration extends AbstractFileConfiguration 136 { 137 141 static String include = "include"; 142 143 144 private boolean includesAllowed = true; 145 146 147 private String header; 148 149 156 public PropertiesConfiguration() 157 { 158 setIncludesAllowed(false); 159 } 160 161 169 public PropertiesConfiguration(String fileName) throws ConfigurationException 170 { 171 super(fileName); 172 } 173 174 182 public PropertiesConfiguration(File file) throws ConfigurationException 183 { 184 super(file); 185 } 186 187 195 public PropertiesConfiguration(URL url) throws ConfigurationException 196 { 197 super(url); 198 } 199 200 206 public static String getInclude() 207 { 208 return PropertiesConfiguration.include; 209 } 210 211 217 public static void setInclude(String inc) 218 { 219 PropertiesConfiguration.include = inc; 220 } 221 222 229 protected void setIncludesAllowed(boolean includesAllowed) 230 { 231 this.includesAllowed = includesAllowed; 232 } 233 234 239 public boolean getIncludesAllowed() 240 { 241 return this.includesAllowed; 242 } 243 244 249 public String getHeader() 250 { 251 return header; 252 } 253 254 259 public void setHeader(String header) 260 { 261 this.header = header; 262 } 263 264 274 public synchronized void load(Reader in) throws ConfigurationException 275 { 276 PropertiesReader reader = new PropertiesReader(in); 277 278 try 279 { 280 while (true) 281 { 282 String line = reader.readProperty(); 283 284 if (line == null) 285 { 286 break; } 288 289 int equalSign = line.indexOf('='); 290 if (equalSign > 0) 291 { 292 String key = line.substring(0, equalSign).trim(); 293 String value = line.substring(equalSign + 1).trim(); 294 295 300 if (StringUtils.isNotEmpty(getInclude()) 301 && key.equalsIgnoreCase(getInclude())) 302 { 303 if (getIncludesAllowed()) 304 { 305 String [] files = StringUtils.split(value, getDelimiter()); 306 for (int i = 0; i < files.length; i++) 307 { 308 load(ConfigurationUtils.locate(getBasePath(), files[i].trim())); 309 } 310 } 311 } 312 else 313 { 314 addProperty(key, unescapeJava(value, getDelimiter())); 315 } 316 } 317 } 318 } 319 catch (IOException ioe) 320 { 321 throw new ConfigurationException("Could not load configuration from input stream.", ioe); 322 } 323 } 324 325 330 public void save(Writer writer) throws ConfigurationException 331 { 332 try 333 { 334 PropertiesWriter out = new PropertiesWriter(writer, getDelimiter()); 335 336 if (header != null) 337 { 338 BufferedReader reader = new BufferedReader (new StringReader (header)); 339 String line; 340 while ((line = reader.readLine()) != null) 341 { 342 out.writeComment(line); 343 } 344 out.write("\n"); 345 } 346 347 out.writeComment("written by PropertiesConfiguration"); 348 out.writeComment(new Date ().toString()); 349 out.write("\n"); 350 351 Iterator keys = getKeys(); 352 while (keys.hasNext()) 353 { 354 String key = (String ) keys.next(); 355 Object value = getProperty(key); 356 357 if (value instanceof List ) 358 { 359 out.writeProperty(key, (List ) value); 360 } 361 else 362 { 363 out.writeProperty(key, value); 364 } 365 } 366 367 out.flush(); 368 } 369 catch (IOException e) 370 { 371 throw new ConfigurationException(e.getMessage(), e); 372 } 373 } 374 375 381 public void setBasePath(String basePath) 382 { 383 super.setBasePath(basePath); 384 setIncludesAllowed(StringUtils.isNotEmpty(basePath)); 385 } 386 387 393 public static class PropertiesReader extends LineNumberReader 394 { 395 400 public PropertiesReader(Reader reader) 401 { 402 super(reader); 403 } 404 405 414 public String readProperty() throws IOException 415 { 416 StringBuffer buffer = new StringBuffer (); 417 418 while (true) 419 { 420 String line = readLine(); 421 if (line == null) 422 { 423 return null; 425 } 426 427 line = line.trim(); 428 429 if (StringUtils.isEmpty(line) || (line.charAt(0) == '#')) 431 { 432 continue; 433 } 434 435 if (line.endsWith("\\")) 436 { 437 line = line.substring(0, line.length() - 1); 438 buffer.append(line); 439 } 440 else 441 { 442 buffer.append(line); 443 break; 444 } 445 } 446 return buffer.toString(); 447 } 448 } 450 453 public static class PropertiesWriter extends FilterWriter 454 { 455 private char delimiter; 456 457 462 public PropertiesWriter(Writer writer, char delimiter) 463 { 464 super(writer); 465 this.delimiter = delimiter; 466 } 467 468 475 public void writeProperty(String key, Object value) throws IOException 476 { 477 write(key); 478 write(" = "); 479 if (value != null) 480 { 481 String v = StringEscapeUtils.escapeJava(String.valueOf(value)); 482 v = StringUtils.replace(v, String.valueOf(delimiter), "\\" + delimiter); 483 write(v); 484 } 485 486 write('\n'); 487 } 488 489 495 public void writeProperty(String key, List values) throws IOException 496 { 497 for (int i = 0; i < values.size(); i++) 498 { 499 writeProperty(key, values.get(i)); 500 } 501 } 502 503 509 public void writeComment(String comment) throws IOException 510 { 511 write("# " + comment + "\n"); 512 } 513 } 515 525 protected static String unescapeJava(String str, char delimiter) 526 { 527 if (str == null) 528 { 529 return null; 530 } 531 int sz = str.length(); 532 StringBuffer out = new StringBuffer (sz); 533 StringBuffer unicode = new StringBuffer (4); 534 boolean hadSlash = false; 535 boolean inUnicode = false; 536 for (int i = 0; i < sz; i++) 537 { 538 char ch = str.charAt(i); 539 if (inUnicode) 540 { 541 unicode.append(ch); 544 if (unicode.length() == 4) 545 { 546 try 549 { 550 int value = Integer.parseInt(unicode.toString(), 16); 551 out.append((char) value); 552 unicode.setLength(0); 553 inUnicode = false; 554 hadSlash = false; 555 } 556 catch (NumberFormatException nfe) 557 { 558 throw new ConfigurationRuntimeException("Unable to parse unicode value: " + unicode, nfe); 559 } 560 } 561 continue; 562 } 563 564 if (hadSlash) 565 { 566 hadSlash = false; 568 569 if (ch=='\\'){ 570 out.append('\\'); 571 } 572 else if (ch=='\''){ 573 out.append('\''); 574 } 575 else if (ch=='\"'){ 576 out.append('"'); 577 } 578 else if (ch=='r'){ 579 out.append('\r'); 580 } 581 else if (ch=='f'){ 582 out.append('\f'); 583 } 584 else if (ch=='t'){ 585 out.append('\t'); 586 } 587 else if (ch=='n'){ 588 out.append('\n'); 589 } 590 else if (ch=='b'){ 591 out.append('\b'); 592 } 593 else if (ch==delimiter){ 594 out.append('\\'); 595 out.append(delimiter); 596 } 597 else if (ch=='u'){ 598 inUnicode = true; 600 } 601 else { 602 out.append(ch); 603 } 604 605 continue; 606 } 607 else if (ch == '\\') 608 { 609 hadSlash = true; 610 continue; 611 } 612 out.append(ch); 613 } 614 615 if (hadSlash) 616 { 617 out.append('\\'); 620 } 621 622 return out.toString(); 623 } 624 625 } 626 | Popular Tags |