001    /*
002        Licensed to the Apache Software Foundation (ASF) under one
003        or more contributor license agreements.  See the NOTICE file
004        distributed with this work for additional information
005        regarding copyright ownership.  The ASF licenses this file
006        to you under the Apache License, Version 2.0 (the
007        "License"); you may not use this file except in compliance
008        with the License.  You may obtain a copy of the License at
009    
010           http://www.apache.org/licenses/LICENSE-2.0
011    
012        Unless required by applicable law or agreed to in writing,
013        software distributed under the License is distributed on an
014        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015        KIND, either express or implied.  See the License for the
016        specific language governing permissions and limitations
017        under the License.  
018     */
019    package org.apache.wiki.htmltowiki;
020    
021    import java.util.Iterator;
022    import java.util.Map;
023    import java.util.Properties;
024    import java.util.TreeMap;
025    
026    /**
027     * some usefull methods for properties
028     *
029     * @version 1.0
030     */
031    // FIXME3.0 move to utils package
032    public final class PropertiesUtils
033    {
034        private static final String OTHER_WHITESPACE = "\t\r\n\014";
035        private static final char[] HEXDIGIT = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
036    
037        /** Private constructor to prevent instantiation. */
038        private PropertiesUtils()
039        {}
040    
041        /**
042         * <p>
043         * like Properties.store, but stores the properties in sorted order
044         * </p>
045         *
046         * @param properties the properties object
047         * @return String the properties, nicely formatted 
048         */
049        @SuppressWarnings("unchecked")
050        public static String toSortedString( Properties properties )
051        {
052            TreeMap treemap = new TreeMap( properties );
053            String string = "";
054            Iterator iterator = treemap.entrySet().iterator();
055            while( iterator.hasNext() )
056            {
057                Map.Entry entry = (Map.Entry)iterator.next();
058                String key = (String)entry.getKey();
059                String value = entry.getValue() == null ? "null" : entry.getValue().toString();
060                string += toLine( key, value ) + '\n';
061            }
062            return string;
063        }
064    
065        /**
066         * Generates a property file line from a supplied key and value.
067         * @param key the property's key
068         * @param value the property's value
069         * @return the converted string
070         */
071        public static String toLine( String key, String value )
072        {
073            return saveConvert( key, true ) + '=' + saveConvert( value, false );
074        }
075    
076        /**
077         * Encodes a property file string from a supplied key/value line.
078         * @param string the string to encode
079         * @param encodeWhiteSpace <code>true</code> if whitespace should be encoded also
080         * @return the converted string
081         */
082        public static String saveConvert( String string, boolean encodeWhiteSpace )
083        {
084            int i = string.length();
085            StringBuffer stringbuffer = new StringBuffer( i * 2 );
086            for( int i3 = 0; i3 < i; i3++ )
087            {
088                char c = string.charAt( i3 );
089                switch( c )
090                {
091                    case ' ':
092                        if( i3 == 0 || encodeWhiteSpace )
093                        {
094                            stringbuffer.append( '\\' );
095                        }
096                        stringbuffer.append( ' ' );
097                        break;
098                    case '\\':
099                        stringbuffer.append( '\\' );
100                        stringbuffer.append( '\\' );
101                        break;
102                    case '\t':
103                        stringbuffer.append( '\\' );
104                        stringbuffer.append( 't' );
105                        break;
106                    case '\n':
107                        stringbuffer.append( '\\' );
108                        stringbuffer.append( 'n' );
109                        break;
110                    case '\r':
111                        stringbuffer.append( '\\' );
112                        stringbuffer.append( 'r' );
113                        break;
114                    case '\014':
115                        stringbuffer.append( '\\' );
116                        stringbuffer.append( 'f' );
117                        break;
118                    default:
119                        if( c < 32 || c > 126 )
120                        {
121                            stringbuffer.append( '\\' );
122                            stringbuffer.append( 'u' );
123                            stringbuffer.append( toHex( c >> 12 & 0xf ) );
124                            stringbuffer.append( toHex( c >> 8 & 0xf ) );
125                            stringbuffer.append( toHex( c >> 4 & 0xf ) );
126                            stringbuffer.append( toHex( c & 0xf ) );
127                        }
128                        else
129                        {
130                            if( OTHER_WHITESPACE.indexOf( c ) != -1 )
131                            {
132                                stringbuffer.append( '\\' );
133                            }
134                            stringbuffer.append( c );
135                        }
136                }
137            }
138            return stringbuffer.toString();
139        }
140    
141        private static char toHex( int i )
142        {
143            return HEXDIGIT[i & 0xf];
144        }
145    }