1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package javax.xml.transform.stream; 19 20 class FilePathToURI { 21 22 // which ASCII characters need to be escaped 23 private static boolean gNeedEscaping[] = new boolean[128]; 24 // the first hex character if a character needs to be escaped 25 private static char[] gAfterEscaping1 = new char[128]; 26 // the second hex character if a character needs to be escaped 27 private static char[] gAfterEscaping2 = new char[128]; 28 private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7', 29 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 30 // initialize the above 3 arrays 31 static { 32 for (int i = 0; i <= 0x1f; i++) { 33 gNeedEscaping[i] = true; 34 gAfterEscaping1[i] = gHexChs[i >> 4]; 35 gAfterEscaping2[i] = gHexChs[i & 0xf]; 36 } 37 gNeedEscaping[0x7f] = true; 38 gAfterEscaping1[0x7f] = '7'; 39 gAfterEscaping2[0x7f] = 'F'; 40 char[] escChs = {' ', '<', '>', '#', '%', '"', '{', '}', 41 '|', '\\', '^', '~', '[', ']', '`'}; 42 int len = escChs.length; 43 char ch; 44 for (int i = 0; i < len; i++) { 45 ch = escChs[i]; 46 gNeedEscaping[ch] = true; 47 gAfterEscaping1[ch] = gHexChs[ch >> 4]; 48 gAfterEscaping2[ch] = gHexChs[ch & 0xf]; 49 } 50 } 51 52 // To escape a file path to a URI, by using %HH to represent 53 // special ASCII characters: 0x00~0x1F, 0x7F, ' ', '<', '>', '#', '%' 54 // and '"' and non-ASCII characters (whose value >= 128). filepath2URI(String path)55 public static String filepath2URI(String path){ 56 // return null if path is null. 57 if (path == null) 58 return null; 59 60 char separator = java.io.File.separatorChar; 61 path = path.replace(separator, '/'); 62 63 int len = path.length(), ch; 64 StringBuilder buffer = new StringBuilder(len*3); 65 buffer.append("file://"); 66 // change C:/blah to /C:/blah 67 if (len >= 2 && path.charAt(1) == ':') { 68 ch = Character.toUpperCase(path.charAt(0)); 69 if (ch >= 'A' && ch <= 'Z') { 70 buffer.append('/'); 71 } 72 } 73 74 // for each character in the path 75 int i = 0; 76 for (; i < len; i++) { 77 ch = path.charAt(i); 78 // if it's not an ASCII character, break here, and use UTF-8 encoding 79 if (ch >= 128) 80 break; 81 if (gNeedEscaping[ch]) { 82 buffer.append('%'); 83 buffer.append(gAfterEscaping1[ch]); 84 buffer.append(gAfterEscaping2[ch]); 85 // record the fact that it's escaped 86 } 87 else { 88 buffer.append((char)ch); 89 } 90 } 91 92 // we saw some non-ascii character 93 if (i < len) { 94 // get UTF-8 bytes for the remaining sub-string 95 byte[] bytes = null; 96 byte b; 97 try { 98 bytes = path.substring(i).getBytes("UTF-8"); 99 } catch (java.io.UnsupportedEncodingException e) { 100 // should never happen 101 return path; 102 } 103 len = bytes.length; 104 105 // for each byte 106 for (i = 0; i < len; i++) { 107 b = bytes[i]; 108 // for non-ascii character: make it positive, then escape 109 if (b < 0) { 110 ch = b + 256; 111 buffer.append('%'); 112 buffer.append(gHexChs[ch >> 4]); 113 buffer.append(gHexChs[ch & 0xf]); 114 } 115 else if (gNeedEscaping[b]) { 116 buffer.append('%'); 117 buffer.append(gAfterEscaping1[b]); 118 buffer.append(gAfterEscaping2[b]); 119 } 120 else { 121 buffer.append((char)b); 122 } 123 } 124 } 125 126 return buffer.toString(); 127 } 128 129 }//FilePathToURI 130