/* * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.net.www.protocol.jrt; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedAction; import jdk.internal.jimage.ImageLocation; import jdk.internal.jimage.ImageReader; import jdk.internal.jimage.ImageReaderFactory; import jdk.internal.loader.URLClassPath; import jdk.internal.loader.Resource; import sun.net.www.ParseUtil; import sun.net.www.URLConnection; /** * URLConnection implementation that can be used to connect to resources * contained in the runtime image. */ public class JavaRuntimeURLConnection extends URLConnection { // ImageReader to access resources in jimage private static final ImageReader reader; static { PrivilegedAction pa = ImageReaderFactory::getImageReader; reader = AccessController.doPrivileged(pa); } // the module and resource name in the URL private final String module; private final String name; // the Resource when connected private volatile Resource resource; JavaRuntimeURLConnection(URL url) throws IOException { super(url); String path = url.getPath(); if (path.isEmpty() || path.charAt(0) != '/') throw new MalformedURLException(url + " missing path or /"); if (path.length() == 1) { this.module = null; this.name = null; } else { int pos = path.indexOf('/', 1); if (pos == -1) { this.module = path.substring(1); this.name = null; } else { this.module = path.substring(1, pos); this.name = ParseUtil.decode(path.substring(pos+1)); } } } /** * Finds a resource in a module, returning {@code null} if the resource * is not found. */ private static Resource findResource(String module, String name) { if (reader != null) { URL url = toJrtURL(module, name); ImageLocation location = reader.findLocation(module, name); if (location != null && URLClassPath.checkURL(url) != null) { return new Resource() { @Override public String getName() { return name; } @Override public URL getURL() { return url; } @Override public URL getCodeSourceURL() { return toJrtURL(module); } @Override public InputStream getInputStream() throws IOException { byte[] resource = reader.getResource(location); return new ByteArrayInputStream(resource); } @Override public int getContentLength() { long size = location.getUncompressedSize(); return (size > Integer.MAX_VALUE) ? -1 : (int) size; } }; } } return null; } @Override public synchronized void connect() throws IOException { if (!connected) { if (name == null) { String s = (module == null) ? "" : module; throw new IOException("cannot connect to jrt:/" + s); } resource = findResource(module, name); if (resource == null) throw new IOException(module + "/" + name + " not found"); connected = true; } } @Override public InputStream getInputStream() throws IOException { connect(); return resource.getInputStream(); } @Override public long getContentLengthLong() { try { connect(); return resource.getContentLength(); } catch (IOException ioe) { return -1L; } } @Override public int getContentLength() { long len = getContentLengthLong(); return len > Integer.MAX_VALUE ? -1 : (int)len; } @Override public Permission getPermission() { return new RuntimePermission("accessSystemModules"); } /** * Returns a jrt URL for the given module and resource name. */ private static URL toJrtURL(String module, String name) { try { return new URL("jrt:/" + module + "/" + name); } catch (MalformedURLException e) { throw new InternalError(e); } } /** * Returns a jrt URL for the given module. */ private static URL toJrtURL(String module) { try { return new URL("jrt:/" + module); } catch (MalformedURLException e) { throw new InternalError(e); } } }