@ -16,15 +16,11 @@
@@ -16,15 +16,11 @@
package org.springframework.util ;
import java.io.BufferedReader ;
import java.io.BufferedWriter ;
import java.io.IOException ;
import java.io.InputStream ;
import java.io.OutputStream ;
import java.io.Reader ;
import java.io.Writer ;
import java.util.Date ;
import java.util.Enumeration ;
import java.util.Properties ;
/ * *
@ -38,7 +34,7 @@ import java.util.Properties;
@@ -38,7 +34,7 @@ import java.util.Properties;
*
* < p > Loading from and storing to a stream delegates to { @code Properties . load }
* and { @code Properties . store } , respectively , to be fully compatible with
* the Unicode conversion as implemented by the JDK Properties class . On JDK 1 . 6 ,
* the Unicode conversion as implemented by the JDK Properties class . As of JDK 1 . 6 ,
* { @code Properties . load / store } will also be used for readers / writers ,
* effectively turning this class into a plain backwards compatibility adapter .
*
@ -57,167 +53,22 @@ import java.util.Properties;
@@ -57,167 +53,22 @@ import java.util.Properties;
* /
public class DefaultPropertiesPersister implements PropertiesPersister {
// Determine whether Properties.load(Reader) is available (on JDK 1.6+)
private static final boolean loadFromReaderAvailable =
ClassUtils . hasMethod ( Properties . class , "load" , new Class [ ] { Reader . class } ) ;
// Determine whether Properties.store(Writer, String) is available (on JDK 1.6+)
private static final boolean storeToWriterAvailable =
ClassUtils . hasMethod ( Properties . class , "store" , new Class [ ] { Writer . class , String . class } ) ;
public void load ( Properties props , InputStream is ) throws IOException {
props . load ( is ) ;
}
public void load ( Properties props , Reader reader ) throws IOException {
if ( loadFromReaderAvailable ) {
// On JDK 1.6+
props . load ( reader ) ;
}
else {
// Fall back to manual parsing.
doLoad ( props , reader ) ;
}
}
protected void doLoad ( Properties props , Reader reader ) throws IOException {
BufferedReader in = new BufferedReader ( reader ) ;
while ( true ) {
String line = in . readLine ( ) ;
if ( line = = null ) {
return ;
}
line = StringUtils . trimLeadingWhitespace ( line ) ;
if ( line . length ( ) > 0 ) {
char firstChar = line . charAt ( 0 ) ;
if ( firstChar ! = '#' & & firstChar ! = '!' ) {
while ( endsWithContinuationMarker ( line ) ) {
String nextLine = in . readLine ( ) ;
line = line . substring ( 0 , line . length ( ) - 1 ) ;
if ( nextLine ! = null ) {
line + = StringUtils . trimLeadingWhitespace ( nextLine ) ;
}
}
int separatorIndex = line . indexOf ( "=" ) ;
if ( separatorIndex = = - 1 ) {
separatorIndex = line . indexOf ( ":" ) ;
}
String key = ( separatorIndex ! = - 1 ? line . substring ( 0 , separatorIndex ) : line ) ;
String value = ( separatorIndex ! = - 1 ) ? line . substring ( separatorIndex + 1 ) : "" ;
key = StringUtils . trimTrailingWhitespace ( key ) ;
value = StringUtils . trimLeadingWhitespace ( value ) ;
props . put ( unescape ( key ) , unescape ( value ) ) ;
}
}
}
}
protected boolean endsWithContinuationMarker ( String line ) {
boolean evenSlashCount = true ;
int index = line . length ( ) - 1 ;
while ( index > = 0 & & line . charAt ( index ) = = '\\' ) {
evenSlashCount = ! evenSlashCount ;
index - - ;
}
return ! evenSlashCount ;
props . load ( reader ) ;
}
protected String unescape ( String str ) {
StringBuilder result = new StringBuilder ( str . length ( ) ) ;
for ( int index = 0 ; index < str . length ( ) ; ) {
char c = str . charAt ( index + + ) ;
if ( c = = '\\' ) {
c = str . charAt ( index + + ) ;
if ( c = = 't' ) {
c = '\t' ;
}
else if ( c = = 'r' ) {
c = '\r' ;
}
else if ( c = = 'n' ) {
c = '\n' ;
}
else if ( c = = 'f' ) {
c = '\f' ;
}
}
result . append ( c ) ;
}
return result . toString ( ) ;
}
public void store ( Properties props , OutputStream os , String header ) throws IOException {
props . store ( os , header ) ;
}
public void store ( Properties props , Writer writer , String header ) throws IOException {
if ( storeToWriterAvailable ) {
// On JDK 1.6+
props . store ( writer , header ) ;
}
else {
// Fall back to manual parsing.
doStore ( props , writer , header ) ;
}
}
protected void doStore ( Properties props , Writer writer , String header ) throws IOException {
BufferedWriter out = new BufferedWriter ( writer ) ;
if ( header ! = null ) {
out . write ( "#" + header ) ;
out . newLine ( ) ;
}
out . write ( "#" + new Date ( ) ) ;
out . newLine ( ) ;
for ( Enumeration keys = props . keys ( ) ; keys . hasMoreElements ( ) ; ) {
String key = ( String ) keys . nextElement ( ) ;
String val = props . getProperty ( key ) ;
out . write ( escape ( key , true ) + "=" + escape ( val , false ) ) ;
out . newLine ( ) ;
}
out . flush ( ) ;
props . store ( writer , header ) ;
}
protected String escape ( String str , boolean isKey ) {
int len = str . length ( ) ;
StringBuilder result = new StringBuilder ( len * 2 ) ;
for ( int index = 0 ; index < len ; index + + ) {
char c = str . charAt ( index ) ;
switch ( c ) {
case ' ' :
if ( index = = 0 | | isKey ) {
result . append ( '\\' ) ;
}
result . append ( ' ' ) ;
break ;
case '\\' :
result . append ( "\\\\" ) ;
break ;
case '\t' :
result . append ( "\\t" ) ;
break ;
case '\n' :
result . append ( "\\n" ) ;
break ;
case '\r' :
result . append ( "\\r" ) ;
break ;
case '\f' :
result . append ( "\\f" ) ;
break ;
default :
if ( "=: \t\r\n\f#!" . indexOf ( c ) ! = - 1 ) {
result . append ( '\\' ) ;
}
result . append ( c ) ;
}
}
return result . toString ( ) ;
}
public void loadFromXml ( Properties props , InputStream is ) throws IOException {
props . loadFromXML ( is ) ;
}