/*
 * 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.
/** * 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<ImageReader> 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 null if the resource is not found.
/** * 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.
/** * 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.
/** * 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); } } }