1 /* 2 * Copyright (c) 1998, 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.misc; 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 */ 50 public abstract String getName(); 51 52 /** 53 * Returns the URL of the Resource. 54 */ 55 public abstract URL getURL(); 56 57 /** 58 * Returns the CodeSource URL for the Resource. 59 */ 60 public abstract URL getCodeSourceURL(); 61 62 /** 63 * Returns an InputStream for reading the Resource data. 64 */ 65 public abstract InputStream getInputStream() throws IOException; 66 67 /** 68 * Returns the length of the Resource data, or -1 if unknown. 69 */ 70 public abstract int getContentLength() throws IOException; 71 72 private InputStream cis; 73 74 /* Cache result in case getBytes is called after getByteBuffer. */ 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 */ 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 (b.length < pos + bytesToRead) { 117 b = Arrays.copyOf(b, pos + bytesToRead); 118 } 119 } else { 120 bytesToRead = b.length - pos; 121 } 122 int cc = 0; 123 try { 124 cc = in.read(b, pos, bytesToRead); 125 } catch (InterruptedIOException iioe) { 126 Thread.interrupted(); 127 isInterrupted = true; 128 } 129 if (cc < 0) { 130 if (len != Integer.MAX_VALUE) { 131 throw new EOFException("Detect premature EOF"); 132 } else { 133 if (b.length != pos) { 134 b = Arrays.copyOf(b, pos); 135 } 136 break; 137 } 138 } 139 pos += cc; 140 } 141 } finally { 142 try { 143 in.close(); 144 } catch (InterruptedIOException iioe) { 145 isInterrupted = true; 146 } catch (IOException ignore) {} 147 148 if (isInterrupted) { 149 Thread.currentThread().interrupt(); 150 } 151 } 152 return b; 153 } 154 155 /** 156 * Returns the Resource data as a ByteBuffer, but only if the input stream 157 * was implemented on top of a ByteBuffer. Return <tt>null</tt> otherwise. 158 */ 159 public ByteBuffer getByteBuffer() throws IOException { 160 InputStream in = cachedInputStream(); 161 if (in instanceof ByteBuffered) { 162 return ((ByteBuffered)in).getByteBuffer(); 163 } 164 return null; 165 } 166 167 /** 168 * Returns the Manifest for the Resource, or null if none. 169 */ 170 public Manifest getManifest() throws IOException { 171 return null; 172 } 173 174 /** 175 * Returns theCertificates for the Resource, or null if none. 176 */ 177 public java.security.cert.Certificate[] getCertificates() { 178 return null; 179 } 180 181 /** 182 * Returns the code signers for the Resource, or null if none. 183 */ 184 public CodeSigner[] getCodeSigners() { 185 return null; 186 } 187 } 188