1 /* 2 * Copyright (c) 2014, 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.net.www.protocol.jrt; 27 28 import java.io.ByteArrayInputStream; 29 import java.io.File; 30 import java.io.FilePermission; 31 import java.io.IOException; 32 import java.io.InputStream; 33 import java.net.MalformedURLException; 34 import java.net.URL; 35 import java.security.AccessController; 36 import java.security.Permission; 37 import java.security.PrivilegedAction; 38 import java.util.List; 39 40 import jdk.internal.jimage.ImageLocation; 41 import jdk.internal.jimage.ImageReader; 42 import jdk.internal.jimage.ImageReaderFactory; 43 44 import jdk.internal.loader.URLClassPath; 45 import jdk.internal.loader.Resource; 46 import sun.net.www.ParseUtil; 47 import sun.net.www.URLConnection; 48 49 /** 50 * URLConnection implementation that can be used to connect to resources 51 * contained in the runtime image. 52 */ 53 public class JavaRuntimeURLConnection extends URLConnection { 54 55 // ImageReader to access resources in jimage 56 private static final ImageReader reader = ImageReaderFactory.getImageReader(); 57 58 // the module and resource name in the URL 59 private final String module; 60 private final String name; 61 62 // the Resource when connected 63 private volatile Resource resource; 64 65 // the permission to access resources in the runtime image, created lazily 66 private static volatile Permission permission; 67 68 JavaRuntimeURLConnection(URL url) throws IOException { 69 super(url); 70 String path = url.getPath(); 71 if (path.length() == 0 || path.charAt(0) != '/') 72 throw new MalformedURLException(url + " missing path or /"); 73 if (path.length() == 1) { 74 this.module = null; 75 this.name = null; 76 } else { 77 int pos = path.indexOf('/', 1); 78 if (pos == -1) { 79 this.module = path.substring(1); 80 this.name = null; 81 } else { 82 this.module = path.substring(1, pos); 83 this.name = ParseUtil.decode(path.substring(pos+1)); 84 } 85 } 86 } 87 88 /** 89 * Finds a resource in a module, returning {@code null} if the resource 90 * is not found. 91 */ 92 private static Resource findResource(String module, String name) { 93 if (reader != null) { 94 URL url = toJrtURL(module, name); 95 ImageLocation location = reader.findLocation(module, name); 96 if (location != null && URLClassPath.checkURL(url) != null) { 97 return new Resource() { 98 @Override 99 public String getName() { 100 return name; 101 } 102 @Override 103 public URL getURL() { 104 return url; 105 } 106 @Override 107 public URL getCodeSourceURL() { 108 return toJrtURL(module); 109 } 110 @Override 111 public InputStream getInputStream() throws IOException { 112 byte[] resource = reader.getResource(location); 113 return new ByteArrayInputStream(resource); 114 } 115 @Override 116 public int getContentLength() { 117 long size = location.getUncompressedSize(); 118 return (size > Integer.MAX_VALUE) ? -1 : (int) size; 119 } 120 }; 121 } 122 } 123 return null; 124 } 125 126 @Override 127 public synchronized void connect() throws IOException { 128 if (!connected) { 129 if (name == null) { 130 String s = (module == null) ? "" : module; 131 throw new IOException("cannot connect to jrt:/" + s); 132 } 133 resource = findResource(module, name); 134 if (resource == null) 135 throw new IOException(module + "/" + name + " not found"); 136 connected = true; 137 } 138 } 139 140 @Override 141 public InputStream getInputStream() throws IOException { 142 connect(); 143 return resource.getInputStream(); 144 } 145 146 @Override 147 public long getContentLengthLong() { 148 try { 149 connect(); 150 return resource.getContentLength(); 151 } catch (IOException ioe) { 152 return -1L; 153 } 154 } 155 156 @Override 157 public int getContentLength() { 158 long len = getContentLengthLong(); 159 return len > Integer.MAX_VALUE ? -1 : (int)len; 160 } 161 162 @Override 163 public Permission getPermission() throws IOException { 164 Permission p = permission; 165 if (p == null) { 166 // using lambda expression here leads to recursive initialization 167 PrivilegedAction<String> pa = new PrivilegedAction<String>() { 168 public String run() { return System.getProperty("java.home"); } 169 }; 170 String home = AccessController.doPrivileged(pa); 171 p = new FilePermission(home + File.separator + "-", "read"); 172 permission = p; 173 } 174 return p; 175 } 176 177 /** 178 * Returns a jrt URL for the given module and resource name. 179 */ 180 private static URL toJrtURL(String module, String name) { 181 try { 182 return new URL("jrt:/" + module + "/" + name); 183 } catch (MalformedURLException e) { 184 throw new InternalError(e); 185 } 186 } 187 188 /** 189 * Returns a jrt URL for the given module. 190 */ 191 private static URL toJrtURL(String module) { 192 try { 193 return new URL("jrt:/" + module); 194 } catch (MalformedURLException e) { 195 throw new InternalError(e); 196 } 197 } 198 }