Incompatibilidades entre Eclipse 3.1 e 3.2

O Eclipse foi alterado de formas incompatíveis entre as versões 3.1 e 3.2 de modo a afetar os plug-ins. As entradas a seguir descrevem as áreas alteradas e fornecem instruções para migrar plug-ins 3.1 para 3.2. Observe que você só precisará consultar estas instruções se estiver tendo problemas na execução do plug-in 3.1 na versão 3.2.

  1. Recursos não mais necessariamente no sistema de arquivos local
  2. Alterações de API para MultiPageEditorSite
  3. Alterações de conteúdo em config.ini
  4. Alterações de conteúdo em aplicativos implementados jnlp
  5. Chamadas explícitas para Bundle.start() forçar o pacote configurável a ser ativado no próximo reinício
  6. Sublinhado não mais substituído por hífen em números de versões de plug-ins

1. Recursos Não Mais Necessariamente no Sistema de Arquivos Local

O que é afetado: Clientes da API IWorkspace que assumem que os recursos estão armazenados no sistema de arquivos local.

Descrição: Antes do Eclipse 3.2, cada IResource existente tinha um arquivo ou um diretório correspondente em um sistema de arquivos acessível pelo java.io.File. No Eclipse 3.2, foi incluído suporte para criar recursos cujo conteúdo está armazenado em um sistema de arquivos de suporte obrigatório. Os recursos que utilizam esse suporte não podem mais ser representados diretamente como um java.io.File.

Ação requerida: O método antigo IResource.getLocation() retorna o caminho do sistema de arquivos local de um recurso. Esse método retorna nulo para os recursos que não estão armazenados no sistema de arquivos local. A maioria dos responsáveis pela chamada de getLocation() faziam assim para obter uma instância de java.io.File, que não pode mais ser utilizada para recursos que não estão armazenados no sistema de arquivos local.

O novo plug-in org.eclipse.core.filesystem fornece uma API de sistema de arquivo genérico que pode ser utilizada no lugar de java.io.File. Particularmente, uma instância de org.eclipse.core.filesystem.IFileStore fornece a maior parte dos mesmos métodos que estão disponíveis em java.io.File. O snippet de código a seguir obtém uma instância de IFileStore para um determinado recurso:

   IResource resource = ...;//some resource
   IFileStore store = EFS.getStore(resource.getLocationURI());

A tabela a seguir fornece métodos equivalentes em IFileStore para operações em geral efetuadas com java.io.File:

java.io.FileIFileStore
excluirexcluir
getNamegetName
getParentgetParent
listchildNames
mkdirmkdir(EFS.SHALLOW, null)
mkdirsmkdir(EFS.NONE, null)
renameTomover
new FileInputStream(file)openInputStream
new FileOutputStream(file)openOutputStream

Na API IFileStore, a maior parte das informações sobre um arquivo é armazenada em uma estrutura chamada IFileInfo, obtida chamando IFileStore.fetchInfo(). Esse design permite maior otimização sobre código utilizando java.io.File, porque muitos atributos sobre um arquivo podem muitas vezes ser obtidos com uma única chamada de sistema de arquivos. Observe que as informações em um IFileInfo se tornarão antigas se o arquivo básico for alterado; por isso, as instâncias só deverão ser mantidas enquanto forem necessárias. Aqui estão alguns métodos no java.io.File que têm métodos equivalentes no IFileInfo:

java.io.FileIFileInfo
canWriteisReadOnly
existsexists
getNamegetName
isDirectoryisDirectory
isFile!isDirectory()
isHiddenisHidden
lastModifiedgetLastModified
lengthgetLength
setLastModifiedsetLastModified
setReadOnlysetAttribute(EFS.ATTRIBUTE_READ_ONLY, true)

Como um exemplo concreto, o código que anteriormente estava chamando java.io.File.exists() agora pode chamar IFileStore.fetchInfo().exists(). Quando um IFileInfo é modificado, o resultado precisa ser armazenado novamente utilizando o método IFileStore.putInfo. Por exemplo, este snippet inverte o atributo de leitura em um arquivo:

   IFileStore store = ...;//some file store
   IFileInfo info = store.fetchInfo();
   boolean readOnly = info.getAttribute(EFS.ATTRIBUTE_READ_ONLY);
   info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, !readOnly);
   store.putInfo(info, EFS.SET_ATTRIBUTES, null);

IProjectDescription.getLocation()

Como com o método getLocation(), o local da descrição do projeto pode não ser mais no sistema de arquivos local. O método IProjectDescription.getLocationURI() pode ser utilizado para obter o local de um recurso em um sistema de arquivos arbitrário.

Cache Local

Alguns clientes devem realmente ter uma representação local de um arquivo. Por exemplo, eles podem estar ativando uma ferramenta nativa nesse arquivo ou utilizando bibliotecas que não detectam o Eclipse as quais só identificam recursos de sistema de arquivos (como java.util.zip.ZipFile). Nesses casos, é possível pedir para que um IFileStore retorne uma cópia local armazenada em cache de seu conteúdo:

   IFileStore store = ...;//some file store
   //see if it can directly be represented as a local file
   java.io.File local = store.toLocalFile(EFS.NONE, null);
   //if not, ask for a cached local copy of the file
   if (local == null)
      local = store.toLocalFile(EFS.CACHE, null);

Observe que uma vez obtida uma cópia armazenada em cache de um arquivo, ela não permanecerá em sincronização com o sistema de arquivos real do qual ela se originou. A modificação da cópia armazenada em cache não fará com que o arquivo básico seja modificado.

Falha Aceitável

Os clientes que não podem manipular recursos fora do sistema de arquivos local ainda podem querer adaptar o código deles para que falhem sem muitos problemas. Os clientes podem verificar se um recurso está no sistema de arquivos local e ignorar o recurso ou alertar o usuário quando eles encontrarem um recurso que não podem manipular. Para determinar se um recurso está no sistema de arquivos local, é necessário descobrir seu esquema de sistema de arquivos. Isso pode ser obtido de um recurso da seguinte forma:

   IResource resource = ...;//some resource
   URI uri = resource.getLocationURI();
   if (uri != null && EFS.SCHEME_LOCAL.equals(uri.getScheme())) {
      //file is in local file system
   } else {
      //file is not in the local file system
   }

Se você tiver uma instância IFileStore em mãos, poderá obter o esquema da seguinte forma:

   IFileStore store = ...;//a file store
   store.getFileSystem().getScheme();

2. Alterações de API para MultiPageEditorSite

O que é afetado: Clientes que chamam MultiPageEditorSite.progressStart() ou MultiPageEditorSite.progressEnd().

Descrição: Durante o desenvolvimento do Eclipse 3.0, esses métodos foram incluídos como parte do trabalho de suporte a melhorias. Antes do release 3.0, a maneira na qual o progresso era tratado foi alterada, e esse método não é mais necessário. Por erro do programador, esses métodos públicos foram deixados no release 3.0. Esses dois métodos nunca foram úteis a nenhuma função em um release do Eclipse; por isso, foram excluídos.

Ação requerida: Clientes que chamam MultiPageEditorSite.progressStart() ou MultiPageEditorSite.progressEnd() deverão passar a utilizar IWorkbenchSiteProgressService em seu lugar.

3. Alterações de Conteúdo em config.ini

O que é afetado: Clientes que têm um config.ini customizado e estão mudando seu aplicativo para 3.2.

Descrição: Antes da versão 3.2, o valor típico para osgi.bundles contido no config.ini era org.eclipse.core.runtime@2:start, org.eclipse.update.configurator@3:start. Por causa da refatoração do tempo de execução, esse valor precisa ser atualizado para que o aplicativo seja iniciado com êxito.

Ação requerida: Altere o valor de osgi.bundles para incluir org.eclipse.equinox.common@2:start, org.eclipse.update.configurator@3:start, org.eclipse.core.runtime@start.

4. Alterações de conteúdo em aplicativos implementados jnlp

O que é afetado: Clientes que estão implementando aplicativos RCP e especificaram um valor para osgi.bundles.

Descrição: Antes da versão 3.2, o valor típico para osgi.bundles contido no arquivo jnlp principal era org.eclipse.core.runtime@2:start, org.eclipse.update.configurator@3:start. Por causa da refatoração do tempo de execução, esse valor precisa ser atualizado; caso contrário, NullPointerExceptions poderão ser lançadas, impedindo o início do aplicativo.

Ação requerida: Altere o valor de osgi.bundles para incluir org.eclipse.equinox.common@2:start, org.eclipse.update.configurator@3:start, org.eclipse.core.runtime@start.

5. Chamadas Explícitas para Bundle.start() Forçar o Pacote Configurável a Ser Ativado no Próximo Reinício

O que é afetado: Clientes que chamam Bundle.start().

Descrição: No Eclipse, um pacote configurável é especificado como sendo de início lento, utilizando o cabeçalho Eclipse-LazyStart (ou o cabeçalho Eclipse-AutoStart reprovado). No Eclipse 3.1, o método org.osgi.framework.Bundle.start() não marcou os pacotes configuráveis de início lento como iniciados persistentemente. Visto que pacotes configuráveis de início lento nunca foram marcados como persistentemente iniciados, eles não seriam iniciados automaticamente quando o eclipse fosse reiniciado. O javadoc para Bundle.start() declara que deve ocorrer o seguinte quando o método é chamado:

"Registrar persistentemente que esse pacote configurável foi iniciado. Quando o Framework for reiniciado, esse pacote configurável deverá ser iniciado automaticamente."

No Eclipse 3.2, o método Bundle.start() foi corrigido para marcar corretamente o pacote configurável como iniciado persistentemente, mesmo que ele seja de início lento. Essa correção foi obrigada a ser compatível com a especificação OSGi Framework. Como resultado, os responsáveis pela chamada de Bundle.start() forçarão o pacote configurável a ser iniciado quando o Eclipse for reiniciado. Em geral, isso é considerado uma prática ruim, já que provocará a ativação de pacotes configuráveis desnecessários toda vez que o Eclipse for iniciado. Em alguns casos, poderá causar resultados inesperados, como o erro 134412.

Ação requerida: Clientes de Bundle.start() precisam avaliar se sua intenção é ativar persistentemente o pacote configurável a cada reinício. Se essa não for a intenção, os clientes deverão encontrar outra maneira de ativar o pacote configurável. Na maioria dos casos, as chamadas Bundle.start() podem ser evitadas, simplesmente permitindo que o pacote configurável de destino seja ativado lentamente quando as classes forem carregadas a partir deles. Há cenários raros que exigem a ativação dinâmica de um pacote configurável de início lento, mas não marcado persistente para ativação em um reinício. Esses tipos de cenários devem utilizar Bundle.loadClass() para carregar uma classe do pacote configurável que precisa ser ativada, em vez de chamar Bundle.start().

5. Sublinhado Não Mais Substituído por Hífen em Números de Versões de Plug-in

No Eclipse 3.0, o uso de um caractere de sublinhado ('_') no segmento de qualificador de um identificador de versão não era suportado, mas também não era obrigatório. Se um identificador de versão de plug-in contivesse um sublinhado no qualificador, esse caractere era transformado em um hífen ('-') ao exportar o plug-in para o sistema de arquivo e também ao instalar o plug-in de um site de atualização.
No Eclipse 3.1, as regras para caracteres permitidos em qualificadores foram relaxadas para incluir o caractere de sublinhado; assim, quando um plug-in ofensivo era exportado ou instalado, o qualificador não era modificado de seu estado original. Essa alteração sutil foi acidentalmente deixada de fora do guia de migração de 3.0 para 3.1. A continuação da história (e no Eclipse 3.2) é que estamos mantendo a compatibilidade com o Eclipse 3.1 e os plug-ins que utilizam caracteres de sublinhado em seus qualificadores de versão deverão estar cientes das alterações mencionadas anteriormente quando lidarem com versões de plug-in antigas (ao exportar e quando existirem em sites de atualização). Isso significa, por exemplo, que os provedores de plug-in que tiverem versões antigas de plug-in em um site de atualização deverão assegurar-se de que o nome no sistema de arquivo corresponda ao nome do plug-in.