1 /* 2 * Copyright (c) 1998, 2019, 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 jdk.internal.loader; 27 28 import java.io.EOFException; 29 import java.net.URL; 30 import java.io.IOException; 31 import java.io.InterruptedIOException; 32 import java.io.InputStream; 33 import java.security.CodeSigner; 34 import java.util.jar.Manifest; 35 import java.nio.ByteBuffer; 36 import java.util.Arrays; 37 import sun.nio.ByteBuffered; 38 39 /** 40 * This class is used to represent a Resource that has been loaded 41 * from the class path. 42 * 43 * @author David Connelly 44 * @since 1.2 45 */ 46 public abstract class Resource { 47 /** 48 * Returns the name of the Resource. 49 */ getName()50 public abstract String getName(); 51 52 /** 53 * Returns the URL of the Resource. 54 */ getURL()55 public abstract URL getURL(); 56 57 /** 58 * Returns the CodeSource URL for the Resource. 59 */ getCodeSourceURL()60 public abstract URL getCodeSourceURL(); 61 62 /** 63 * Returns an InputStream for reading the Resource data. 64 */ getInputStream()65 public abstract InputStream getInputStream() throws IOException; 66 67 /** 68 * Returns the length of the Resource data, or -1 if unknown. 69 */ getContentLength()70 public abstract int getContentLength() throws IOException; 71 72 private InputStream cis; 73 74 /* Cache result in case getBytes is called after getByteBuffer. */ cachedInputStream()75 private synchronized InputStream cachedInputStream() throws IOException { 76 if (cis == null) { 77 cis = getInputStream(); 78 } 79 return cis; 80 } 81 82 /** 83 * Returns the Resource data as an array of bytes. 84 */ getBytes()85 public byte[] getBytes() throws IOException { 86 byte[] b; 87 // Get stream before content length so that a FileNotFoundException 88 // can propagate upwards without being caught too early 89 InputStream in = cachedInputStream(); 90 91 // This code has been uglified to protect against interrupts. 92 // Even if a thread has been interrupted when loading resources, 93 // the IO should not abort, so must carefully retry, failing only 94 // if the retry leads to some other IO exception. 95 96 boolean isInterrupted = Thread.interrupted(); 97 int len; 98 for (;;) { 99 try { 100 len = getContentLength(); 101 break; 102 } catch (InterruptedIOException iioe) { 103 Thread.interrupted(); 104 isInterrupted = true; 105 } 106 } 107 108 try { 109 b = new byte[0]; 110 if (len == -1) len = Integer.MAX_VALUE; 111 int pos = 0; 112 while (pos < len) { 113 int bytesToRead; 114 if (pos >= b.length) { // Only expand when there's no room 115 bytesToRead = Math.min(len - pos, b.length + 1024); 116 if (bytesToRead < 0) { 117 // Can overflow only due to large b.length 118 bytesToRead = len - pos; 119 } 120 b = Arrays.copyOf(b, pos + bytesToRead); 121 } else { 122 bytesToRead = b.length - pos; 123 } 124 int cc = 0; 125 try { 126 cc = in.read(b, pos, bytesToRead); 127 } catch (InterruptedIOException iioe) { 128 Thread.interrupted(); 129 isInterrupted = true; 130 } 131 if (cc < 0) { 132 if (len != Integer.MAX_VALUE) { 133 throw new EOFException("Detect premature EOF"); 134 } else { 135 if (b.length != pos) { 136 b = Arrays.copyOf(b, pos); 137 } 138 break; 139 } 140 } 141 pos += cc; 142 } 143 } finally { 144 try { 145 in.close(); 146 } catch (InterruptedIOException iioe) { 147 isInterrupted = true; 148 } catch (IOException ignore) {} 149 150 if (isInterrupted) { 151 Thread.currentThread().interrupt(); 152 } 153 } 154 return b; 155 } 156 157 /** 158 * Returns the Resource data as a ByteBuffer, but only if the input stream 159 * was implemented on top of a ByteBuffer. Return {@code null} otherwise. 160 * @return Resource data or null. 161 */ getByteBuffer()162 public ByteBuffer getByteBuffer() throws IOException { 163 InputStream in = cachedInputStream(); 164 if (in instanceof ByteBuffered) { 165 return ((ByteBuffered)in).getByteBuffer(); 166 } 167 return null; 168 } 169 170 /** 171 * Returns the Manifest for the Resource, or null if none. 172 */ getManifest()173 public Manifest getManifest() throws IOException { 174 return null; 175 } 176 177 /** 178 * Returns theCertificates for the Resource, or null if none. 179 */ getCertificates()180 public java.security.cert.Certificate[] getCertificates() { 181 return null; 182 } 183 184 /** 185 * Returns the code signers for the Resource, or null if none. 186 */ getCodeSigners()187 public CodeSigner[] getCodeSigners() { 188 return null; 189 } 190 } 191