Helyfüggetlen hozzáférés az erőforrásokhoz
- Áttekintés
- Források, nevek és kontextusok
- Rendszeres erőforrások
- Nem rendszeres erőforrások
- Forrásnevek
- Using Methods of java.lang.Class
- Using Methods ofjava.lang.ClassLoader
- Security
- Examples
Overview
A forrás olyan adat (kép, hang, szöveg stb.), amelyet egy programnak a programkód helyétől független módon kell elérnie. A Java programok két mechanizmust használhatnakaz erőforrások eléréséhez: Az appletek a Applet.getCodeBase()
t használják az appletkód alap-URL-jének megadására, majd az alap-URL-t egy relatív elérési úttal bővítik a kívánt erőforrás betöltéséhez, például a Applet.getAudioClip(url)
-vel. Az alkalmazások “jól ismert helyeket” használnak, mint példáulSystem.getProperty("user.home")
vagySystem.getProperty("java.home")
, majd hozzáadják a”/lib/resource”-t, és megnyitják ezt a fájlt.
A Class
ésClassLoader
osztályok metódusai egy helyfüggetlen módot biztosítanak az erőforrások betöltésére. Például lehetővé teszik az erőforrások megtalálását:
- Az internetről több HTTPkapcsolat segítségével betöltött applet.
- A JAR fájlok segítségével betöltött applet.
- A CLASSPATH-ba betöltött vagy telepített Java Bean.
- A CLASSPATH-ba telepített “könyvtár”.
Ezek a módszerek nem nyújtanak külön támogatást a lokalizált erőforrások megtalálására. A lokalizált erőforrásokat a nemzetköziesítési lehetőségek támogatják.
Források, nevek és kontextusok
A forrást egy olyan karakterlánc azonosítja, amely egy sor alsztringből áll, amelyet ferdehúzás (/) határol, majd az erőforrás neve követ.Minden alsztringnek érvényes Java azonosítónak kell lennie. Az erőforrás neve shortName
vagy shortName.extension
alakú. AshortName
és a extension
is Java azonosítónak kell lennie.
Az erőforrás neve független a Java-implementációtól; különösen, hogy az útvonalválasztó mindig ferde (/). Azonban a Java implementáció szabályozza annak részleteit, hogy az erőforrás tartalma hogyan képződik le egy fájlba, adatbázisba vagy más, a tényleges erőforrást tartalmazó objektumba.
Az erőforrás nevének értelmezése relatív az osztálybetöltő példányához. AClassLoader
osztály által implementált metódusok végzik ezt az értelmezést.
Rendszer erőforrás
A rendszer erőforrás olyan erőforrás, amely vagy a rendszerbe van beépítve, vagy amelyet a hoszt implementáció tart például egy helyi fájlrendszerben. A programok aClassLoader
getSystemResource
ésgetSystemResourceAsStream
metódusokon keresztül érik el a rendszererőforrásokat.
Egy adott implementációban például egy rendszererőforrás megtalálása magában foglalhatja a CLASSPATH bejegyzéseiben való keresést. AClassLoader
metódusok a CLASSPATH minden egyes könyvtár, ZIP fájl vagy JAR fájl bejegyzését átkutatják az erőforrás fájl után, és ha megtalálják, akkor vagy egy InputStream
, vagy az erőforrás nevét adják vissza. Ha nem találják, a metódusok nullát adnak vissza. Az erőforrás a CLASSPATH más bejegyzésében is megtalálható, mint ahová az osztályfájlt betöltötték.
Non-System Resources
A getResource
végrehajtása egy osztály betöltésénél a ClassLoader
osztály részleteitől függ. Például AppletClassLoader
:
- Először megpróbálja megtalálni az erőforrást rendszererőforrásként; majd,ha nem találja,
- Keres az ebben a CODEBASE-ben már betöltött archívumokban (JAR fájlok) lévő erőforrások között; majd,ha nem találja,
- A CODEBASE-t használja és megpróbálja megtalálni az erőforrást (ami egy távoli helyszínnel való kapcsolatfelvételt jelenthet).
Minden osztálybetöltő először rendszerforrásként keresi az erőforrást, az osztályfájlok kereséséhez hasonló módon. Ez a keresési szabály lehetővé teszi bármely erőforrás helyi felülírását. Az ügyfeleknek olyan erőforrásnevet kell választaniuk, amely egyedi lesz (például a cég- vagy csomagnevet használva előtagként).
Az erőforrásnevek
Az osztály által használt erőforrás nevére vonatkozó általános konvenció az, hogy az osztály csomagjának teljes minősítésű nevét használják, de az összes pontot (.) átváltoztatják perjelre (/), és hozzáadnak egy name.extension
formájú erőforrásnevet. Ennek támogatására, valamint a rendszerosztályok (amelyek esetében agetClassLoader
nullát ad vissza) részleteinek egyszerűbb kezelése érdekében az osztályClass
két kényelmi metódust biztosít, amelyek meghívják a ClassLoader
megfelelő metódusait.
A Class
metódusnak adott erőforrásnévnek lehet egy “/” kezdőbetűje, amely “abszolút” névként azonosítja.Az olyan erőforrásnevek, amelyek nem kezdődnek “/”-vel, “relatívak”.
Az abszolút nevekből eltávolítjuk a kezdő “/”-t, és minden további módosítás nélkül átadjuk a megfelelőClassLoader
metódusnak az erőforrás megtalálására. A relatív neveket a korábban ismertetett konvenció szerint módosítjuk, majd átadjuk egy ClassLoader
metódusnak.
Using Methods of java.lang.Class
A Class
osztály több metódust is implementál az erőforrások betöltésére.
A getResource()
metódus visszaadja az erőforrás URL-jét. Az URL (és annak reprezentációja) az implementációra és a JVM-re jellemző (vagyis az egyik futásidejű példányban kapott URL nem biztos, hogy egy másikban működik). A protokollja általában az erőforrást betöltő ClassLoader
-ra jellemző. Haaz erőforrás nem létezik vagy biztonsági megfontolások miatt nem látható, a metódusok nullát adnak vissza.
Ha a klienskód az erőforrás tartalmát InputStream
ként akarja olvasni, akkor az URL-re alkalmazhatja aopenStream()
metódust. Ez elég gyakori ahhoz, hogy indokolja a getResourceAsStream()
hozzáadását aClass
-hoz és a ClassLoader
-hoz. ugyanaz, mint agetResource().openStream()
hívása, kivéve, hogy agetResourceAsStream()
az IO kivételeket elkapja, és egy null InputStream
-t ad vissza.
A klienskód az erőforrás tartalmát objektumként is kérheti a java.net.URL.getContent()
módszer alkalmazásával az URL-en. Ez akkor hasznos, ha az erőforrás például egy kép adatait tartalmazza. Kép esetén az eredmény egy awt.image.ImageProducer
objektum, nem pedig egyImage
objektum.
A getResource
és getResourceAsStream
metódusok egy adott nevű erőforrást keresnek. Null értéket adnak vissza, ha nem találnak erőforrást a megadott névvel. Az adott osztályhoz tartozó erőforrások keresésének szabályait az osztályClassLoader-je hajtja végre. A Class
metódusok aClassLoader
metódusokhoz delegálnak, miután egy névadási konvenciót alkalmaztak: ha az erőforrás neve “/”-vel kezdődik, akkor úgy használjuk, ahogy van.Ellenkező esetben a csomag neve előtagot kap, miután az összes pontot (.) átváltoztattuk kötőjelekké (/).
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);}
A resolveName
metódus hozzáad egy csomagnév előtagot, ha a név nem abszolút, és eltávolítja a vezető “/”-t, ha a név abszolút. Lehetséges, bár nem gyakori, hogy különböző csomagokban lévő osztályok ugyanazt az erőforrást használják.
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
A ClassLoader
osztály kétféle metódussal rendelkezik az erőforrások eléréséhez. Az egyik készlet egy InputStream
erőforrást ad vissza. A másik készlet egy URL-t ad vissza. A InputStream
-t visszaadó metódusok könnyebben használhatók és sok igényt kielégítenek, míg az URL-t visszaadó metódusok bonyolultabb információkhoz, például egy képhez és egy AudioCliphez biztosítanak hozzáférést.
A ClassLoader
az osztályok kezeléséhez hasonlóan kezeli az erőforrásokat. A ClassLoader
szabályozza, hogyan kapcsolja össze egy erőforrás nevét annak tartalmával. A ClassLoader
a rendszer erőforrásainak eléréséhez is biztosít metódusokat,a rendszerosztályokhoz hasonlóan. A Class
osztály biztosít néhány kényelmi metódust, amelyek a funkciókat a ClassLoader
metódusokra delegálják.
Minden Java program közvetve, az I18N (lokalizációs) API-kon keresztül éri el ezeket a metódusokat. Mások a Class
metódusain keresztül férnek hozzá. Néhányan közvetlenül hívják meg aClassLoader
metódusokat.
A ClassLoader
metódusok a megadott karakterláncot használják az erőforrás neveként anélkül, hogy abszolút/relatív transzformációt alkalmaznának (lásd a Class metódusokat). A név nem tartalmazhat egy vezető “/” betűt.
A rendszer erőforrásai azok, amelyeket a hosztimplementáció közvetlenül kezel. Például aCLASSPATH-ban találhatók.
Az erőforrás neve egy “/”-vel elválasztott azonosítósorozat. A Class
osztály kényelmi módszereket biztosít az erőforrások eléréséhez; a módszerek egy olyan konvenciót valósítanak meg, ahol a csomag neve elé az erőforrás rövid neve kerül.
A források elérhetők InputStream
, vagy egyURL formájában.
A getSystemResourceAsStream
módszer visszaad egyInputStream-et a megadott rendszererőforráshoz, vagy null, ha nem találja az erőforrást. Az erőforrás neve bármilyen rendszerforrás lehet.
A getSystemResource
módszer megtalálja a megadott nevű rendszerforrást. Visszaadja az erőforrás URL-címét vagy null, ha nem találja az erőforrást. Ajava.net.URL.getContent()
meghívása az URL-lel egy objektumot ad vissza, például ImageProducer
, AudioClip
vagy InputStream
.
A getResourceAsStream
módszer egyInputStream
-t ad vissza a megadott erőforráshoz vagy nullát, ha nem találja az erőforrást.
A getResource
módszer egy erőforrást talál a megadott névvel. Visszaadja az erőforrás URL-címét, vagy null, ha nem találja az erőforrást. Ajava.net.URL.getContent()
meghívása az URL-lel egy olyan objektumot ad vissza, mint ImageProducer
, AudioClip
vagy InputStream
.
Biztonság
Mivel a getResource()
hozzáférést biztosít az információkhoz,jól meghatározott és megalapozott biztonsági szabályokkal kell rendelkeznie. Ha a biztonsági megfontolások nem teszik lehetővé, hogy egy erőforrás látható legyen valamilyen biztonsági kontextusban, a getResource()
metódus sikertelen lesz (nullát ad vissza), mintha az erőforrás egyáltalán nem lenne jelen, eza létezési támadásokat kezeli.
Az osztálybetöltők nem biztosíthatnak hozzáférést egy .classfile tartalmához, mind biztonsági, mind teljesítménybeli okokból. Az, hogy lehetséges-e URL-t kapni egy .class fájlhoz, az alábbiakban bemutatottak szerint a sajátosságoktól függ.
Nincsenek meghatározott biztonsági problémák vagy korlátozások a nem rendszer osztálybetöltő által talált erőforrásokkal kapcsolatban.A AppletClassLoader
hozzáférést biztosít a forráshelyről betöltött információkhoz, akár egyenként, akár egy JAR-fájlon keresztül csoportosan; így a AppletClassLoader
nek ugyanazokat a checkConnect()
szabályokat kell alkalmaznia, amikor az URL-eket a getResource()
-n keresztül kezeli.
A rendszer ClassLoader
hozzáférést biztosít a CLASSPATH-ban lévő információkhoz. A CLASSPATH tartalmazhat könyvtárakat és JAR fájlokat. Mivel egy JAR-fájlt szándékosan hozunk létre, más jelentősége van, mint egy könyvtárnak, ahol a dolgok véletlenszerűbben véget érhetnek. Különösen szigorúbbak vagyunk abban, hogy egy könyvtárból információt kapjunk, mint egy JAR-fájlból.
Ha egy erőforrás egy könyvtárban van:
-
getResource()
a meghívások aFile.exists()
segítségével határozzák meg, hogy a megfelelő fájlt láthatóvá tegyék-e a felhasználó számára. Emlékezzünk arra, hogy aFile.exists()
acheckRead()
metódust használja a biztonsági kezelőben. - ugyanez vonatkozik a
getResourceAsStream()
-ra.
Ha az erőforrás egy JAR fájlban van:
-
getResource()
a meghívás minden fájl esetében sikeres lesz, függetlenül attól, hogy a meghívás egy rendszeren belüli vagy egy nem rendszeren belüli osztályból történik. -
getResourceAsStream()
a meghívások sikeresek lesznek a nem .class erőforrások esetében, és így ajava.net.URL.getContent()
megfelelő URL-eken is.
Példák
Ez a szakasz két példát mutat be az ügyfélkódra. Az első példa “abszolút erőforrásneveket” és hagyományos mechanizmusokat használ egy Class
objektum kinyeréséhez.
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. }}
Ez a példa “relatív erőforrásneveket” és a fordító által a -experimental
jelzőn keresztül elérhető mechanizmust használja egy Class
objektum kinyeréséhez.
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. }
.