1 /* 2 * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.nio.fs; 27 28 import java.net.URI; 29 import java.net.URISyntaxException; 30 31 /** 32 * Utility methods to convert between Path and URIs. 33 */ 34 35 class WindowsUriSupport { 36 private WindowsUriSupport() { 37 } 38 39 // suffix for IPv6 literal address 40 private static final String IPV6_LITERAL_SUFFIX = ".ipv6-literal.net"; 41 42 /** 43 * Returns URI to represent the given (absolute) path 44 */ 45 private static URI toUri(String path, boolean isUnc, boolean addSlash) { 46 String uriHost; 47 String uriPath; 48 49 if (isUnc) { 50 int slash = path.indexOf('\\', 2); 51 uriHost = path.substring(2, slash); 52 uriPath = path.substring(slash).replace('\\', '/'); 53 54 // handle IPv6 literal addresses 55 // 1. drop .ivp6-literal.net 56 // 2. replace "-" with ":" 57 // 3. replace "s" with "%" (zone/scopeID delimiter) 58 if (uriHost.endsWith(IPV6_LITERAL_SUFFIX)) { 59 uriHost = uriHost 60 .substring(0, uriHost.length() - IPV6_LITERAL_SUFFIX.length()) 61 .replace('-', ':') 62 .replace('s', '%'); 63 } 64 } else { 65 uriHost = ""; 66 uriPath = "/" + path.replace('\\', '/'); 67 } 68 69 // append slash if known to be directory 70 if (addSlash) 71 uriPath += "/"; 72 73 // return file:///C:/My%20Documents or file://server/share/foo 74 try { 75 return new URI("file", uriHost, uriPath, null); 76 } catch (URISyntaxException x) { 77 if (!isUnc) 78 throw new AssertionError(x); 79 } 80 81 // if we get here it means we've got a UNC with reserved characters 82 // in the server name. The authority component cannot contain escaped 83 // octets so fallback to encoding the server name into the URI path 84 // component. 85 uriPath = "//" + path.replace('\\', '/'); 86 if (addSlash) 87 uriPath += "/"; 88 try { 89 return new URI("file", null, uriPath, null); 90 } catch (URISyntaxException x) { 91 throw new AssertionError(x); 92 } 93 } 94 95 /** 96 * Converts given Path to a URI 97 */ 98 static URI toUri(WindowsPath path) { 99 path = path.toAbsolutePath(); 100 String s = path.toString(); 101 102 // trailing slash will be added if file is a directory. Skip check if 103 // already have trailing space 104 boolean addSlash = false; 105 if (!s.endsWith("\\")) { 106 try { 107 addSlash = WindowsFileAttributes.get(path, true).isDirectory(); 108 } catch (WindowsException x) { 109 } 110 } 111 112 return toUri(s, path.isUnc(), addSlash); 113 } 114 115 /** 116 * Converts given URI to a Path 117 */ 118 static WindowsPath fromUri(WindowsFileSystem fs, URI uri) { 119 if (!uri.isAbsolute()) 120 throw new IllegalArgumentException("URI is not absolute"); 121 if (uri.isOpaque()) 122 throw new IllegalArgumentException("URI is not hierarchical"); 123 String scheme = uri.getScheme(); 124 if ((scheme == null) || !scheme.equalsIgnoreCase("file")) 125 throw new IllegalArgumentException("URI scheme is not \"file\""); 126 if (uri.getRawFragment() != null) 127 throw new IllegalArgumentException("URI has a fragment component"); 128 if (uri.getRawQuery() != null) 129 throw new IllegalArgumentException("URI has a query component"); 130 String path = uri.getPath(); 131 if (path.isEmpty()) 132 throw new IllegalArgumentException("URI path component is empty"); 133 134 // UNC 135 String auth = uri.getRawAuthority(); 136 if (auth != null && !auth.isEmpty()) { 137 String host = uri.getHost(); 138 if (host == null) 139 throw new IllegalArgumentException("URI authority component has undefined host"); 140 if (uri.getUserInfo() != null) 141 throw new IllegalArgumentException("URI authority component has user-info"); 142 if (uri.getPort() != -1) 143 throw new IllegalArgumentException("URI authority component has port number"); 144 145 // IPv6 literal 146 // 1. drop enclosing brackets 147 // 2. replace ":" with "-" 148 // 3. replace "%" with "s" (zone/scopeID delimiter) 149 // 4. Append .ivp6-literal.net 150 if (host.startsWith("[")) { 151 host = host.substring(1, host.length()-1) 152 .replace(':', '-') 153 .replace('%', 's'); 154 host += IPV6_LITERAL_SUFFIX; 155 } 156 157 // reconstitute the UNC 158 path = "\\\\" + host + path; 159 } else { 160 if ((path.length() > 2) && (path.charAt(2) == ':')) { 161 // "/c:/foo" --> "c:/foo" 162 path = path.substring(1); 163 } 164 } 165 return WindowsPath.parse(fs, path); 166 } 167 }