Locatie-onafhankelijke toegang tot bronnen

  • Overzicht
  • Bronnen, namen en contexten
  • Systeembronnen
  • Niet-systeembronnen
  • Bronnennamen
  • Methoden gebruiken van java.lang.Class
  • Methoden van java.lang.ClassLoader
  • Veiligheid
  • Voorbeelden

Overzicht

Een resource is data (afbeeldingen, audio, tekst, enzovoort) waar een programma toegang toe moet krijgen op een manier die onafhankelijk is van de locatie van de programmacode. Java-programma’s kunnen twee mechanismen gebruiken om toegang te krijgen tot bronnen: Applets gebruiken Applet.getCodeBase() om de basisURL voor de applet-code te krijgen en breiden dan de basisURL uit met een relatief pad om de gewenste bron te laden, bijvoorbeeld met Applet.getAudioClip(url). Applicaties gebruiken “bekende locaties” zoalsSystem.getProperty("user.home") ofSystem.getProperty("java.home"), voegen dan “/lib/resource” toe, en openen dat bestand.

Methods in de klassen Class enClassLoader bieden een locatie-onafhankelijke manier om bronnen te lokaliseren. Ze maken bijvoorbeeld het lokaliseren van bronnen mogelijk voor:

  • Een applet geladen van het Internet met behulp van meerdere HTTP-connecties.
  • Een applet geladen met behulp van JAR-bestanden.
  • Een Java Bean geladen of geïnstalleerd in het CLASSPATH.
  • Een “library” geïnstalleerd in het CLASSPATH.

Deze methoden bieden geen specifieke ondersteuning voor het lokaliseren van gelokaliseerde bronnen. Gelokaliseerde bronnen worden ondersteund door de internationaliseringsfaciliteiten.

Bronnen, namen en contexten

Een bron wordt geïdentificeerd door een tekenreeks die bestaat uit een opeenvolging van subtekenreeksen, begrensd door schuine strepen (/), gevolgd door een bronnaam.Elke subtekenreeks moet een geldige Java-identifier zijn. De naam van de bron is van de vorm shortName ofshortName.extension. ZowelshortName als extension moeten Java identifiers zijn.

De naam van een resource is onafhankelijk van de Java-implementatie; in het bijzonder, het pad scheidingsteken is altijd een schuine streep (/). De Java-implementatie bepaalt echter in detail hoe de inhoud van de resource wordt toegewezen aan een bestand, een database of een ander object dat de eigenlijke resource bevat.

De interpretatie van een resource-naam is relatief ten opzichte van een instantie van de classloader. Methoden die zijn geïmplementeerd door de klasse ClassLoader doen deze interpretatie.

Systeemhulpbronnen

Een systeemhulpbron is een hulpbron die ofwel is ingebouwd in het systeem, of wordt bewaard door de host-implementatie in, bijvoorbeeld, een lokaal bestandssysteem. Programma’s hebben toegang tot systeembronnen via deClassLoader methoden getSystemResource engetSystemResourceAsStream.

In een bepaalde implementatie kan het lokaliseren van een systeembron bijvoorbeeld bestaan uit het doorzoeken van de ingangen in het CLASSPATH. DeClassLoader methoden zoeken in elke directory, ZIP-bestand, of JAR-bestand in het CLASSPATH naar het bronbestand, en, indien gevonden, retourneert het ofwel een InputStream, of de bronnaam. Indien niet gevonden, retourneert de methode null. Een resource kan worden gevonden in een andere entry in het CLASSPATH dan de locatie waar het klasse-bestand werd geladen.

Niet-Systeem Hulpbronnen

De implementatie van getResource op een geladen klasse hangt af van de details van de ClassLoader klasse. Bijvoorbeeld, AppletClassLoader:

  • Probeert eerst de bron als een systeembron te vinden; dan, indien niet gevonden,
  • zoekt de bronnen in archieven (JAR-bestanden) die reeds in deze CODEBASE zijn geladen; dan, indien niet gevonden,
  • Gebruikt CODEBASE en probeert de bron te vinden (wat kan inhouden dat contact wordt opgenomen met een externe site).

Alle klasse-loaders zullen een bron eerst als systeembron zoeken, op een wijze die analoog is aan het zoeken naar klasse-bestanden. Deze zoekregel staat het lokaal overschrijven van elke resource toe. Clients moeten een unieke naam voor de resource kiezen (bijvoorbeeld door de bedrijfs- of pakketnaam als prefix te gebruiken).

Resource Namen

Een gebruikelijke conventie voor de naam van een door een klasse gebruikte resource is om de volledig gekwalificeerde naam van het pakket van de klasse te gebruiken, maar alle punten (.) om te zetten in schuine strepen (/), en een resource naam van de vorm name.extension toe te voegen. Om dit te ondersteunen, en om de afhandeling van de details van systeemklassen (waarvoorgetClassLoader null retourneert) te vereenvoudigen, verschaft de klasseClass twee gemaksmethoden die de juiste methoden in ClassLoader aanroepen.

De bronnaam die aan een Class methode wordt gegeven kan een beginnend “/” hebben dat het identificeert als een “absolute” naam.Resourcenamen die niet met een “/” beginnen, zijn “relatief”.

Absolute namen worden ontdaan van hun initiaal “/” en zonder verdere wijziging doorgegeven aan de juiste methode ClassLoader om de bron te lokaliseren. Relativenamen worden gewijzigd volgens de eerder beschreven conventie en worden dan doorgegeven aan een ClassLoader methode.

Methoden van java.lang.Class

De Class klasse implementeert verschillende methoden voor het laden van bronnen.

De methode getResource() retourneert een URL voor de bron. De URL (en de representatie ervan) is specifiek voor de implementatie en de JVM (dat wil zeggen, de URL verkregen in een andereuntime-instantie werkt mogelijk niet in een andere). Het protocol is gewoonlijk specifiek voor de ClassLoader die de bron laadt. Als de bron niet bestaat of niet zichtbaar is vanwege veiligheidsoverwegingen, retourneert de methode null.

Als de client code de inhoud van de bron wil lezen als een InputStream, kan het deopenStream() methode toepassen op de URL. Dit is gebruikelijk genoeg om getResourceAsStream() toe te voegen aanClass en ClassLoader.getResourceAsStream() is hetzelfde als het aanroepen vangetResource().openStream(), behalve datgetResourceAsStream() IO excepties opvangt en een InputStream teruggeeft.

Client code kan ook de inhoud van de bron opvragen als een object door de java.net.URL.getContent() methode op de URL toe te passen. Dit is nuttig wanneer de resource bijvoorbeeld de gegevens van een afbeelding bevat. In het geval van een afbeelding is het resultaat een awt.image.ImageProducer-object, niet eenImage-object.

De methoden getResource engetResourceAsStream zoeken een resource met een gegeven naam. Ze retourneren null als ze geen resource met de opgegeven naam vinden. De regels voor het zoeken naar resources die bij een bepaalde klasse horen, worden geïmplementeerd door deClassLoader van de klasse. De Class methodes delegeren naarClassLoader methodes, na het toepassen van een naamgevingsconventie: als de naam van de resource begint met “/”, wordt deze gebruikt zoals hij is. Anders wordt de naam van het package voorafgegaan, na het converteren van alle punten (.) naar schuine strepen (/).

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);}

De resolveName methode voegt een package naam prefix toe als de naam niet absoluut is, en verwijdert elke voorloop “/” als de naam absoluut is. Het is mogelijk, hoewel ongebruikelijk, om klassen in verschillende pakketten te hebben die dezelfde bron delen.

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;}

Methoden van java.lang.ClassLoader

De ClassLoader klasse heeft twee sets van methoden om toegang te krijgen tot bronnen. Een set retourneert een InputStream voor de bron. De andere set retourneert een URL. De methodes die een InputStream retourneren zijn gemakkelijker te gebruiken en zullen aan veel behoeften voldoen, terwijl de methodes die URLs retourneren toegang geven tot meer complexe informatie, zoals een Afbeelding en een AudioClip.

De ClassLoader wijzigt bronnen op dezelfde manier als de manier waarop het klassen beheert. Een ClassLoader regelt hoe de naam van een bron aan zijn inhoud moet worden gekoppeld. ClassLoader verschaft ook methodes voor toegang tot systeembronnen, analoog aan de systeemklassen. De Classklasse verschaft een aantal gemakkelijke methodes die functionaliteit delegeren naar de ClassLoader methodes.

Vele Java programma’s zullen indirect toegang krijgen tot deze methodes via de I18N (lokalisatie) APIs. Anderen zullen er toegang toe krijgen via methodes in Class. Enkelen zullen de ClassLoader methoden direct aanroepen.

De methoden in ClassLoader gebruiken de gegeven String als de naam van de bron zonder enige absolute/relatieve transformatie toe te passen (zie de methoden in Klasse). De naam mag niet worden voorafgegaan door een “/”.

Systeembronnen zijn bronnen die rechtstreeks door de hostimplementatie worden behandeld. Zij kunnen zich bijvoorbeeld in hetCLASSPATH bevinden.

De naam van een hulpbron is een “/”-gescheiden opeenvolging vanidentifiers. De klasse Class biedt handige methoden voor toegang tot bronnen; de methoden implementeren een conventie waarbij de pakketnaam wordt voorafgegaan door de korte naam van de bron.

Bronnen kunnen worden benaderd als een InputStream, of eenURL.

De methode getSystemResourceAsStream retourneert een InputStream voor de opgegeven systeembron of nul als de bron niet wordt gevonden. De naam van de bron kan elke systeembron zijn.

De methode getSystemResource vindt een systeembron met de opgegeven naam. Zij retourneert een URL naar de bron of null als zij de bron niet vindt. Het aanroepen van java.net.URL.getContent() met de URL zal een object zoals ImageProducer, AudioClip, of InputStream teruggeven.

De methode getResourceAsStream retourneert eenInputStream voor de gespecificeerde resource of null als de resource niet wordt gevonden.

De methode getResource vindt een resource met de gespecificeerde naam. Het retourneert een URL naar de bron of null als de bron niet wordt gevonden. Het aanroepen vanjava.net.URL.getContent() met de URL zal een object zoals ImageProducer, AudioClip, of InputStream teruggeven.

Veiligheid

Omdat getResource() toegang tot informatie verschaft, moet het goed gedefinieerde en gefundeerde veiligheidsregels hebben. Als veiligheidsoverwegingen niet toestaan dat een bron zichtbaar is in een of andere veiligheidscontext, zal de methode getResource() falen (nul teruggeven) alsof de bron helemaal niet aanwezig is, dit adresseert bestaansaanvallen.

Class loaders mogen geen toegang geven tot de inhoud van een .classfile om zowel veiligheids- als prestatieredenen. Of het mogelijk is om een URL voor een .class-bestand te verkrijgen, hangt af van de specifieke kenmerken, zoals hieronder weergegeven.

Er zijn geen gespecificeerde veiligheidskwesties of beperkingen met betrekking tot bronnen die worden gevonden door een niet-systeem class loader.AppletClassLoader verschaft toegang tot informatie die is geladen vanaf een bronlocatie, hetzij individueel, hetzij in een groep via een JAR-bestand; dus AppletClassLoader dient dezelfde checkConnect()-regels toe te passen bij het omgaan met URL’s via getResource().

Het systeem ClassLoader verschaft toegang tot informatie in het CLASSPATH. Een CLASSPATH kan directories en JAR bestanden bevatten. Aangezien een JAR bestand opzettelijk wordt aangemaakt, heeft het een andere betekenis dan een directory waar dingen op een meer toevallige manier in terecht kunnen komen. In het bijzonder zijn we strenger in het verkrijgen van informatie uit een directory dan uit een JAR bestand.

Als een bron in een directory staat:

  • getResource() invocaties zullenFile.exists() gebruiken om te bepalen of het corresponderende bestand zichtbaar moet worden gemaakt voor de gebruiker. Onthoud datFile.exists() de methode checkRead() in de beveiligingsmanager gebruikt.
  • hetzelfde geldt voor getResourceAsStream().

Als de bron zich in een JAR-bestand bevindt:

  • getResource() aanroepen zullen slagen voor alle bestanden, ongeacht of de aanroep wordt gedaan vanuit een systeem of een niet-systeemklasse.
  • getResourceAsStream() aanroepingen zullen slagen voor niet .class bronnen, en zo ook voorjava.net.URL.getContent() op overeenkomstige URLs.

Voorbeelden

Deze sectie geeft twee voorbeelden van client code. Het eerste voorbeeld gebruikt “absolute bron”-namen en traditionele mechanismen om een Class object te krijgen.

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. }}

Dit voorbeeld gebruikt “relatieve bron”-namen en het mechanisme dat beschikbaar is via de -experimentalflag van de compiler, om een Class object te krijgen.

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. }

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.