Acesso Independente da Localização a Recursos

  • Visão Geral
  • Recursos, nomes e contextos
  • Recursos do Sistema
  • Recursos fora do Sistema
  • Nomes dos Recursos
  • Métodos de uso do java.lang.Classe
  • Métodos de uso do java.lang.ClassLoader
  • Segurança
  • Exemplos

Visão geral

Um recurso é um dado (imagens, áudio, texto, etc.) que o programa precisa acessar de forma independente da localização do código do programa. Os programas Java podem usar dois mecanismos para acessar os recursos: Applets usam Applet.getCodeBase() para obter a URL base para o código do applet e depois estender a URL baseURL com um caminho relativo para carregar o recurso desejado, por exemplo com Applet.getAudioClip(url). Os aplicativos usam “locais bem conhecidos” comoSystem.getProperty("user.home") ouSystem.getProperty("java.home"), então adicione”/lib/resource”, e abra esse arquivo.

Métodos nas classes Class eClassLoader fornecem uma forma independente de localização para tolocar recursos. Por exemplo, eles habilitam a localização de recursos para:

  • Um applet carregado da Internet usando múltiplas conexões HTTP.
  • Um applet carregado usando arquivos JAR.
  • Um Java Bean carregado ou instalado no CLASSPATH.
  • Uma “biblioteca” instalada no CLASSPATH.

Esses métodos não fornecem suporte específico para recursos localizados localizados. Recursos localizados são suportados pelos recursos de internacionalização.

Recursos, nomes e contextos

Um recurso é identificado por uma string que consiste em uma seqüência de subestruturas, delimitada por slashes (/), seguida por um nome de recurso.Cada subestrutura deve ser um identificador Java válido. O nome do recurso é do formulário shortName ou shortName.extension. AmbosshortName e extension devem ser identificadores Java.

O nome de um recurso é independente da implementação Java; em particular, o separador de caminhos é sempre uma barra(/). Entretanto, a implementação Java controla os detalhes de como o conteúdo do recurso é mapeado em um arquivo, banco de dados, ou outro objeto contendo o recurso real.

A interpretação do nome de um recurso é relativa a uma instância do classloader. Métodos implementados pela classeClassLoader fazem esta interpretação.

Recursos do Sistema

Um recurso do sistema é um recurso que é embutido no sistema, ou mantido pela implementação do host, por exemplo, em um sistema de arquivos local. Programas acessam recursos do sistema através dos métodosClassLoadergetSystemResource egetSystemResourceAsStream.

Por exemplo, em uma implementação em particular, a localização de um recurso do sistema pode envolver a pesquisa das entradas no CLASSPATH. Os métodosClassLoader pesquisam cada diretório, arquivo ZIP ou entrada de arquivo JAR no CLASSPATH para o arquivo de recurso, e, se encontrado, retorna ou um InputStream, ou o nome do recurso. Se não for encontrado, os métodos retornam nulos. Um recurso pode ser encontrado em uma entrada diferente no CLASSPATH do que o local onde o arquivo de classe foi carregado.

Non-System Resources

A implementação de getResource em um carregador de classes depende dos detalhes da classe ClassLoader. Forexample, AppletClassLoader:

  • Primeiro tenta localizar o recurso como um recurso do sistema; depois, se não for encontrado,
  • Procura através dos recursos em arquivos (arquivos JAR) já carregados neste CODEBASE; depois, se não for encontrado,
  • Usa CODEBASE e tenta localizar o recurso (o que pode envolver o contato com um local remoto).

Todos os carregadores de classe irão procurar por um recurso primeiro como um recurso do sistema, de forma análoga à procura de arquivos de classe. Esta regra de pesquisa permite sobrescrever localmente qualquer recurso. Os clientes devem escolher um nome de recurso que será único (usando o nome da empresa ou do pacote como prefixo, por exemplo).

Nomes de Recursos

Uma convenção comum para o nome de um recurso usado por uma classe é usar o nome totalmente qualificado do pacote da classe, mas converte todos os períodos (.) para cortes (/), e adiciona um nome de recurso do formulário name.extension. Para suportar isto, e para simplificar o manuseio dos detalhes das classes do sistema (para as quaisgetClassLoader retorna nulo), a classeClass fornece dois métodos de conveniência que chamam os métodos apropriados em ClassLoader.

O nome do recurso dado a um método Class pode ter um nome inicial “/” que o identifica como um nome “absoluto”.Os nomes dos recursos que não começam com “/” são “relativos”.

Nomes absolutos são removidos do seu “/” inicial e são passados, sem qualquer outra modificação, para o método apropriadoClassLoader para localizar o recurso. Os nomes relativos são modificados de acordo com a convenção descrita anteriormente e depois são passados para um método ClassLoader.

Using Methods of java.lang.Class

A classe Class implementa vários métodos para carregar recursos.

O método getResource() retorna uma URL para o recurso. A URL (e sua representação) é específica para a implementação e a JVM (ou seja, a URL obtida em instância oneruntime pode não funcionar em outra). Seu protocolo é geralmente específico para a ClassLoader carga do recurso. Se o recurso não existe ou não é visível devido a considerações de segurança, os métodos retornam null.

Se o código do cliente quiser ler o conteúdo do recurso asan InputStream, ele pode aplicar o métodoopenStream() na URL. Isso é comum o suficiente para justificar a adição de getResourceAsStream() aClass e ClassLoader. o mesmo que chamar getResource().openStream(), exceto quegetResourceAsStream() captura exceções IO retorna um anull InputStream.

Código do cliente também pode solicitar o conteúdo do recurso como anobjeto aplicando o método java.net.URL.getContent() na URL. Isto é útil quando o recurso contém os dados de uma imagem, por exemplo. No caso de uma imagem, theresult é um objeto awt.image.ImageProducer, não um objetoImage.

Os métodos getResource egetResourceAsStream encontram um recurso com nome dado. Eles retornam nulos se não encontrarem um recurso com o nome especificado. As regras de busca de recursos associados a uma determinada classe são implementadas pelo class’sClassLoader. Os métodos Class delegam aClassLoader métodos, após aplicar uma convenção de nomes: se o nome do recurso começa com “/”, ele é usado como está. Caso contrário, o nome do pacote é prefixado, após converter todos os períodos (.) para slashes (/).

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

O método resolveName adiciona um prefixo de nome de pacote se o nome não for absoluto, e remove qualquer “/” principal se o nome for absoluto. É possível, embora incomum, ter classes em pacotes diffent compartilhando o mesmo 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;}

Usando métodos do java.lang.ClassLoader

A classe ClassLoader tem dois conjuntos de métodos para acessar recursos. Um conjunto retorna um InputStream para o recurso. O outro conjunto retorna uma URL. Os métodos que retornam um InputStream são mais fáceis de usar e irão satisfazer muitas necessidades, enquanto os métodos que retornam URLs fornecem acesso a informação morecomplexa, como uma Imagem e um AudioClip.

A classe ClassLoader altera os recursos de forma similar ao modo como ela gerencia as classes. A ClassLoader controla como tomap o nome de um recurso ao seu conteúdo. ClassLoader também fornece métodos de acesso aos recursos do sistema, análogos às classes do sistema. A Classclass fornece alguns métodos de conveniência que delegam funcionalidade aos ClassLoader methods.

Muitos programas Java acessarão esses métodos indiretamente através das APIs I18N (localização). Outros irão acessá-la através de métodos em Class. Alguns invocarão diretamente os métodos em ClassLoader methods.

Os métodos em ClassLoader utilizam a String dada pelo nome do recurso sem aplicar nenhuma transformação absoluta/relativa (veja os métodos em Classe). O nome não deve ter um leading “/”.

Recursos do sistema são aqueles que são tratados diretamente pela hostimplemenation. Por exemplo, eles podem estar localizados noCLASSPATH.

O nome de um recurso é uma sequência “/”-separated ofidentifiers. A classe Class fornece conveniencemethods para acessar recursos; os métodos implementam uma convenção onde o nome do pacote é prefixado ao nome curto do recurso.

Recursos podem ser acessados como um InputStream, ou aURL.

O método getSystemResourceAsStream retorna umInputStream para o recurso do sistema especificado ou nulo se ele não encontrar o recurso. O nome do recurso pode ser qualquer recurso do sistema.

O método getSystemResource encontra um recurso do sistema com o nome especificado. Ele retorna um URL para o recurso ou nulo se não encontrar o recurso. Chamandojava.net.URL.getContent() com a URL retornará um anobjeto como ImageProducer, AudioClip,ou InputStream.

O método getResourceAsStream retorna umInputStream para o recurso especificado ou nulo se ele não encontrar o recurso.

O método getResource encontra um recurso com o nome especificado. Ele retorna uma URL para o recurso ou nula se ele não encontrar o recurso. Chamandojava.net.URL.getContent() com a URL irá retornar anobjeto como ImageProducer, AudioClip,ou InputStream.

Segurança

Desde que getResource() forneça acesso à informação,deve ter regras de segurança bem definidas e bem fundamentadas. Considerações de segurança não permitem que um recurso seja visível em um contexto de segurança, o método getResource() falhará (retorno nulo) como se o recurso não estivesse presente, isto resolve os ataques.

Os carregadores de classe podem não fornecer acesso ao conteúdo de um .classfile por razões de segurança e desempenho. Se é possível obter uma URL para um arquivo .class depende das especificações, como mostrado abaixo.

Não há problemas ou restrições de segurança especificados em relação a fontes não-sistemas que são encontradas por um carregador de classes.AppletClassLoader fornece acesso a informações que são carregadas de um local de origem, seja individualmente, ou em grupo através de um arquivo JAR; assim AppletClassLoader deve aplicar as mesmas checkConnect() regras ao lidar com URLs através de getResource().

O sistema ClassLoader fornece acesso a informações no CLASSPATH. Um CLASSPATH pode conter diretórios e arquivos JAR. Como um arquivo JAR é criado intencionalmente, ele tem um significado diferente do que um diretório onde as coisas podem acabar de forma mais casual. Em particular, somos mais rigorosos em obter informações de um diretório do que de um arquivo JAR.

Se um recurso estiver em um diretório:

  • getResource() invocações usarãoFile.exists() para determinar se o arquivo correspondente será visível para o usuário. Lembre-se queFile.exists() usa o método checkRead() no gerenciador de segurança.
  • o mesmo se aplica a getResourceAsStream().

Se o recurso estiver em um arquivo JAR:

  • getResource() invocações serão bem sucedidas para todos os arquivos, independentemente de a invocação ser feita de dentro do asistema ou de uma classe não-sistema.
  • getResourceAsStream() invocations will succeed fornon .class resources, and so will forjava.net.URL.getContent() on corresponding URLs.

Exemplos

Esta seção fornece dois exemplos de código do cliente. O firstexample usa nomes de “recurso absoluto” e mecanismos tradicionais para obter um Class object.

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 exemplo usa nomes de “recurso relativo” e o mecanísmo disponível do compilador através do -experimentalflag, para obter um Class object.

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

Deixe uma resposta

O seu endereço de email não será publicado.