Acceso independiente de la ubicación a los recursos

  • Presentación
  • Recursos, nombres y contextos
  • Recursos del sistema
  • Recursos no del sistema
  • Nombres de recursos
  • Uso de métodos de java.lang.Class
  • Using Methods ofjava.lang.ClassLoader
  • Security
  • Examples

Overview

Un recurso son datos (imágenes, audio, texto, etc.) a los que un programa necesita acceder de forma independiente a la ubicación del código del programa. Los programas Java pueden utilizar dos mecanismos para acceder a los recursos: Los applets utilizan Applet.getCodeBase() para obtener la URL base del código del applet y luego amplían la URL base con una ruta relativa para cargar el recurso deseado, por ejemplo con Applet.getAudioClip(url). Las aplicaciones utilizan «ubicaciones conocidas» comoSystem.getProperty("user.home") oSystem.getProperty("java.home"), luego añaden «/lib/resource», y abren ese archivo.

Los métodos de las clases Class yClassLoader proporcionan una forma independiente de la ubicación para localizar recursos. Por ejemplo, permiten localizar recursos para:

  • Un applet cargado desde Internet usando múltiples conexiones HTTP.
  • Un applet cargado usando archivos JAR.
  • Un Java Bean cargado o instalado en el CLASSPATH.
  • Una «biblioteca» instalada en el CLASSPATH.

Estos métodos no proporcionan soporte específico para localizar recursos localizados. Los recursos localizados son soportados por las facilidades de internacionalización.

Recursos, nombres y contextos

Un recurso es identificado por una cadena que consiste en una secuencia de subcadenas, delimitadas por barras (/), seguidas por un nombre de recurso.Cada subcadena debe ser un identificador Java válido. El nombre del recurso tiene la forma shortName oshortName.extension. Tanto shortName como extensiondeben ser identificadores de Java.

El nombre de un recurso es independiente de la implementación de Java; en particular, el separador de ruta es siempre una barra (/). Sin embargo, la implementación de Java controla los detalles de cómo el contenido del recurso se asigna a un archivo, base de datos, u otro objeto que contiene el recurso real.

La interpretación de un nombre de recurso es relativa a una instancia de cargador de clase. Los métodos implementados por la claseClassLoader hacen esta interpretación.

Recursos del sistema

Un recurso del sistema es un recurso que está incorporado al sistema, o mantenido por la implementación del host en, por ejemplo, un sistema de archivos local. Los programas acceden a los recursos del sistema a través de los métodosClassLoader getSystemResource ygetSystemResourceAsStream.

Por ejemplo, en una implementación particular, la localización de un recurso del sistema puede implicar la búsqueda de las entradas en el CLASSPATH. Los métodosClassLoader buscan en cada directorio, archivo ZIP o archivo JAR en el CLASSPATH el archivo de recursos y, si lo encuentran, devuelven un InputStream o el nombre del recurso. Si no se encuentra, los métodos devuelven null. Un recurso puede ser encontrado en una entrada diferente en el CLASSPATH que la ubicación en la que se cargó el archivo de clase.

Recursos No-Sistema

La implementación de getResource en una carga de clase depende de los detalles de la clase ClassLoader. Por ejemplo, AppletClassLoader:

  • Primero intenta localizar el recurso como un recurso del sistema; luego, si no se encuentra,
  • Busca entre los recursos en archivos (archivos JAR) ya cargados en esta CODEBASE; luego, si no se encuentra,
  • Utiliza CODEBASE e intenta localizar el recurso (lo que puede implicar contactar con un sitio remoto).

Todos los cargadores de clases buscarán un recurso primero como recurso del sistema, de manera análoga a la búsqueda de archivos de clase. Esta regla de búsqueda permite sobrescribir localmente cualquier recurso. Los clientes deben elegir un nombre de recurso que sea único (usando el nombre de la compañía o del paquete como prefijo, por ejemplo).

Nombres de recursos

Una convención común para el nombre de un recurso usado por una clase es usar el nombre completamente calificado del paquete de la clase, pero convertir todos los puntos (.) en barras inclinadas (/), y añadir un nombre de recurso de la forma name.extension. Para apoyar esto, y para simplificar el manejo de los detalles de las clases del sistema (para los que getClassLoader devuelve null), la clase Class proporciona dos métodos de conveniencia que llaman a los métodos apropiados en ClassLoader.

El nombre del recurso dado a un método Class puede tener un «/» inicial que lo identifica como un nombre «absoluto».Los nombres de recursos que no comienzan con una «/» son «relativos».

Los nombres absolutos son despojados de su «/» inicial y son pasados, sin ninguna otra modificación, al métodoClassLoader apropiado para localizar el recurso. Los nombres relativos se modifican de acuerdo con la convención descrita anteriormente y luego se pasan a un método ClassLoader.

Using Methods of java.lang.Class

La clase Class implementa varios métodos para cargar recursos.

El método getResource() devuelve una URL para el recurso. La URL (y su representación) es específica de la implementación y de la JVM (es decir, la URL obtenida en una instancia de tiempo real puede no funcionar en otra). Su protocolo suele ser específico de la ClassLoader que carga el recurso. Si el recurso no existe o no es visible por consideraciones de seguridad, los métodos devuelven null.

Si el código cliente quiere leer el contenido del recurso como un InputStream, puede aplicar el métodoopenStream() sobre la URL. Esto es lo suficientemente común como para justificar la adición de getResourceAsStream() aClass y ClassLoader.getResourceAsStream() es lo mismo que llamar agetResource().openStream(), excepto quegetResourceAsStream() atrapa las excepciones IO y devuelve un InputStream nulo.

El código del cliente también puede solicitar el contenido del recurso como un objeto aplicando el método java.net.URL.getContent() en la URL. Esto es útil cuando el recurso contiene los datos de una imagen, por ejemplo. En el caso de una imagen, el resultado es un objeto awt.image.ImageProducer, no un objetoImage.

Los métodos getResource ygetResourceAsStream buscan un recurso con un nombre dado. Devuelven null si no encuentran un recurso con el nombre especificado. Las reglas de búsqueda de los recursos asociados a una clase dada son implementadas por elClassLoader de la clase. Los métodos Class delegan en los métodosClassLoader, después de aplicar una convención de nomenclatura: si el nombre del recurso empieza por «/», se utiliza tal cual. En caso contrario, se añade el nombre del paquete, después de convertir todos los puntos (.) en barras inclinadas (/).

public InputStream getResourceAsStream(String name) { name = resolveName(name); ClassLoader cl = getClassLoader(); if (cl==null) { return ClassLoader.getSystemResourceAsStream(name); // A system class. } return cl.getResourceAsStream(name);}public java.net.URL getResource(String name) { name = resolveName(name); ClassLoader cl = getClassLoader(); if (cl==null) { return ClassLoader.getSystemResource(name); // A system class. } return cl.getResource(name);}

El método resolveName añade un prefijo al nombre del paquete si el nombre no es absoluto, y elimina cualquier «/» inicial si el nombre es absoluto. Es posible, aunque poco común, tener clases en diferentes paquetes compartiendo el mismo recurso.

private String resolveName(String name) { if (name == null) { return name; } if (!name.startsWith("/")) { Class c = this; while (c.isArray()) { c = c.getComponentType(); } String baseName = c.getName(); int index = baseName.lastIndexOf('.'); if (index != -1) { name = baseName.substring(0, index).replace('.', '/') + "/" + name; } } else { name = name.substring(1); } return name;}

Using Methods of java.lang.ClassLoader

La clase ClassLoader tiene dos conjuntos de métodos para acceder a los recursos. Un conjunto devuelve un InputStream para el recurso. El otro conjunto devuelve una URL. Los métodos que devuelven un InputStream son más fáciles de usar y satisfacen muchas necesidades, mientras que los métodos que devuelven URLs proporcionan acceso a información más compleja, como una imagen y un clip de audio.

La clase ClassLoadermaneja los recursos de forma similar a como gestiona las clases. Un ClassLoader controla cómo asignar el nombre de un recurso a su contenido. ClassLoadertambién proporciona métodos para acceder a los recursos del sistema, de forma análoga a las clases del sistema. La clase Class proporciona algunos métodos de conveniencia que delegan la funcionalidad a los métodos de ClassLoader.

Muchos programas Java accederán a estos métodos indirectamente a través de las APIs de I18N (localización). Otros accederán a través de métodos en Class. Unos pocos invocarán directamente los métodos de ClassLoader.

Los métodos de ClassLoader utilizan el String dado como nombre del recurso sin aplicar ninguna transformación absoluta/relativa (ver los métodos de Class). El nombre no debe tener un «/» inicial.

Los recursos del sistema son aquellos que son manejados directamente por la implementación del host. Por ejemplo, pueden estar ubicados en elCLASSPATH.

El nombre de un recurso es una secuencia de identificadores separados por «/». La clase Class proporciona métodos de conveniencia para acceder a los recursos; los métodos implementan una convención en la que el nombre del paquete se antepone al nombre corto del recurso.

Se puede acceder a los recursos como un InputStream, o unaURL.

El método getSystemResourceAsStream devuelve unInputStream para el recurso del sistema especificado o null si no encuentra el recurso. El nombre del recurso puede ser cualquier recurso del sistema.

El método getSystemResource encuentra un recurso del sistema con el nombre especificado. Devuelve una URL al recurso o null si no encuentra el recurso. Si se llama a java.net.URL.getContent() con la URL, se devuelve un objeto como ImageProducer, AudioClip o InputStream.

El método getResourceAsStream devuelve unInputStream para el recurso especificado o null si no encuentra el recurso.

El método getResource encuentra un recurso con el nombre especificado. Devuelve una URL al recurso o null si no encuentra el recurso. Al llamar a java.net.URL.getContent() con la URL, se devuelve un objeto como ImageProducer, AudioClip o InputStream.

Seguridad

Dado que getResource() proporciona acceso a la información, debe tener reglas de seguridad bien definidas y fundamentadas. Si las consideraciones de seguridad no permiten que un recurso sea visible en algún contexto de seguridad, el método getResource() fallará (devolverá null) como si el recurso no estuviera presente en absoluto, esto aborda los ataques a la existencia.

Los cargadores de clases no pueden proporcionar acceso al contenido de un archivo .class por razones tanto de seguridad como de rendimiento. Si es posible obtener una URL para un archivo .class depende de los detalles, como se muestra a continuación.

No hay problemas de seguridad especificados o restricciones con respecto a los recursos que son encontrados por un cargador de clases que no es del sistema.AppletClassLoader proporciona acceso a la información que se carga desde una ubicación de origen, ya sea individualmente, o en un grupo a través de un archivo JAR; por lo tanto AppletClassLoader debe aplicar las mismas reglas checkConnect() whendealing con URLs a través de getResource().

El sistema ClassLoader proporciona acceso a la información en el CLASSPATH. Un CLASSPATH puede contener directorios y archivos JAR. Dado que un archivo JAR se crea intencionadamente, tiene un significado diferente al de un directorio en el que las cosas pueden acabar de forma más casual. En particular, somos más estrictos a la hora de obtener información de un directorio que de un archivo JAR.

Si un recurso está en un directorio:

  • getResource() las invocaciones utilizaránFile.exists() para determinar si hacer visible al usuario el archivo correspondiente. Recuerde queFile.exists() utiliza el método checkRead() en el gestor de seguridad.
  • Lo mismo se aplica a getResourceAsStream().

Si el recurso está en un archivo JAR:

  • getResource() las invocaciones tendrán éxito para todos los archivos, independientemente de si la invocación se hace desde dentro de una clase del sistema o no.
  • getResourceAsStream() Las invocaciones tendrán éxito para los recursos que no sean de la clase, y también lo tendrán parajava.net.URL.getContent() en las URL correspondientes.

Ejemplos

Esta sección proporciona dos ejemplos de código de cliente. El primer ejemplo utiliza nombres de «recursos absolutos» y mecanismos tradicionales para obtener un objeto Class.

package pkg;import java.io.IOException;import java.io.InputStream;import java.io.PrintStream;class Test { private static final String absName = "/pkg/mumble.baf"; public static void test1() { Class c=null; try { c = Class.forName("pkg.Test"); } catch (Exception ex) { // This should not happen. } InputStream s = c.getResourceAsStream(absName); // do something with it. } public void test2() { InputStream s = this.getClass().getResourceAsStream(absName); // do something with it. }}

Este ejemplo utiliza nombres de «recursos relativos» y el mecanismo disponible en el compilador a través de la bandera -experimental, para obtener un objeto Class.

package pkg;import java.io.IOException;import java.io.InputStream;import java.io.PrintStream;class Test { private static final String relName = "mumble.baf"; public static void test1() { InputStream s = Test.class.getResourceAsStream(relName); // do something with it.} public void test2() { InputStream s = Test.class.getResourceAsStream(relName); // do something with it. }

Deja una respuesta

Tu dirección de correo electrónico no será publicada.