/* * Written by Dawid Kurzyniec and released to the public domain, as explained * at http://creativecommons.org/licenses/publicdomain */ package edu.emory.mathcs.util.classloader; import java.io.*; import java.net.*; import java.security.cert.*; import java.util.jar.*; /** * This class represents a handle (a connection) to some resource, which may * be a class, native library, text file, image, etc. Handles are returned * by {@link edu.emory.mathcs.util.classloader.ResourceLoader}'s <i>get</i> methods. * Having the resource handle, in addition to accessing the resource data * (using methods {@link #getInputStream} or {@link #getBytes}) as well as * access resource metadata, such as attributes, certificates, etc. * <p> * As soon as the handle is no longer in use, it should be explicitly * {@link #close}d, similarly to I/O streams. * * @author Dawid Kurzyniec * @version 1.0 */ @SuppressWarnings("PMD") public abstract class ResourceHandle { /** * Return the name of the resource. The name is a "/"-separated path * name that identifies the resource. */ public abstract String getName(); /** * Returns the URL of the resource. */ public abstract URL getURL(); /** * Returns the CodeSource URL for the class or resource. */ public abstract URL getCodeSourceURL(); /** * Returns and InputStream for reading this resource data. */ public abstract InputStream getInputStream() throws IOException; /** * Returns the length of this resource data, or -1 if unknown. */ public abstract int getContentLength(); /** * Returns this resource data as an array of bytes. */ public byte[] getBytes() throws IOException { byte[] buf; InputStream in = getInputStream(); int len = getContentLength(); try { if (len != -1) { // read exactly len bytes buf = new byte[len]; while (len > 0) { int read = in.read(buf, buf.length - len, len); if (read < 0) { throw new IOException("unexpected EOF"); } len -= read; } } else { // read until end of stream is reached buf = new byte[2048]; int total = 0; while ((len = in.read(buf, total, buf.length - total)) >= 0) { total += len; if (total >= buf.length) { byte[] aux = new byte[total * 2]; System.arraycopy(buf, 0, aux, 0, total); buf = aux; } } // trim if necessary if (total != buf.length) { byte[] aux = new byte[total]; System.arraycopy(buf, 0, aux, 0, total); buf = aux; } } } finally { in.close(); } return buf; } /** * Returns the Manifest of the JAR file from which this resource * was loaded, or null if none. */ public Manifest getManifest() throws IOException { return null; } /** * Return the Certificates of the resource, or null if none. */ public Certificate[] getCertificates() { return null; } /** * Return the Attributes of the resource, or null if none. */ public Attributes getAttributes() throws IOException { Manifest m = getManifest(); if (m == null) return null; String entry = getURL().getFile(); return m.getAttributes(entry); } /** * Closes a connection to the resource indentified by this handle. Releases * any I/O objects associated with the handle. */ public void close() { } // // /** // * Ensures that {@link #release()} method is eventually called when this // * object is finalized. // */ // protected void finalize() throws Throwable { // super.finalize(); // release(); // } public String toString() { return "[" + getName() + ": " + getURL() + "; code source: " + getCodeSourceURL() + "]"; } }