001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.util;
018    
019    import java.io.UnsupportedEncodingException;
020    import java.util.BitSet;
021    
022    import org.apache.commons.logging.Log;
023    import org.apache.commons.logging.LogFactory;
024    
025    
026    public final class UnsafeUriCharactersEncoder {
027        static BitSet unsafeCharacters;
028        private static final transient Log LOG = LogFactory.getLog(UnsafeUriCharactersEncoder.class);
029        private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
030                                                  'D', 'E', 'F'};
031    
032        static {
033            unsafeCharacters = new BitSet(256);
034            unsafeCharacters.set(' ');
035            unsafeCharacters.set('"');
036            unsafeCharacters.set('<');
037            unsafeCharacters.set('>');
038            unsafeCharacters.set('#');
039            unsafeCharacters.set('%');
040            unsafeCharacters.set('{');
041            unsafeCharacters.set('}');
042            unsafeCharacters.set('|');
043            unsafeCharacters.set('\\');
044            unsafeCharacters.set('^');
045            unsafeCharacters.set('~');
046            unsafeCharacters.set('[');
047            unsafeCharacters.set(']');
048            unsafeCharacters.set('`');
049        }
050    
051    
052        private UnsafeUriCharactersEncoder() {
053            // util class
054        }
055    
056        public static String encode(String s) {
057            int n = s.length();
058            if (n == 0) {
059                return s;
060            }
061    
062            // First check whether we actually need to encode
063    
064            try {
065                byte[] bytes = s.getBytes("UTF8");
066                for (int i = 0;;) {
067                    if (unsafeCharacters.get(bytes[i])) {
068                        break;
069                    }
070                    if (++i >= bytes.length) {
071                        return s;
072                    }
073                }
074    
075                StringBuffer sb = new StringBuffer();
076                for (byte b : bytes) {
077                    if (unsafeCharacters.get(b)) {
078                        appendEscape(sb, (byte)b);
079                    } else {
080                        sb.append((char)b);
081                    }
082                }
083                return sb.toString();
084            } catch (UnsupportedEncodingException e) {
085                LOG.error("Can't encoding the uri: ", e);
086                return null;
087            }
088        }
089    
090        private static void appendEscape(StringBuffer sb, byte b) {
091            sb.append('%');
092            sb.append(HEX_DIGITS[(b >> 4) & 0x0f]);
093            sb.append(HEX_DIGITS[(b >> 0) & 0x0f]);
094        }
095    
096    }