Incompatibilidades entre o Eclipse 3.1 e o 3.2

O Eclipse mudou relativamente à incompatibilidade entre o 3.1 e o 3.2 de formas que afectam os plug-ins. As entradas seguintes descrevem as áreas que foram alteradas e facultam instruções para migrar os plug-ins 3.1 para 3.2. Repare que apenas necessita de consultar estas entradas se está a detectar problemas na execução do plug-in 3.1 no 3.2.

  1. Os recursos já não se encontram necessariamente no sistema de ficheiros local
  2. Alterações da API para o MultiPageEditorSite
  3. Alterações do conteúdo no config.ini
  4. Alterações do conteúdo nas aplicações implementadas do jnlp
  5. As chamadas específicas do Bundle.start() obrigam o agrupamento a ser activado no próximo reinício
  6. O traço de sublinhado que não é substituído por hífen nos números das versões de plug-ins

1. Os recursos já não se encontram necessariamente no sistema de ficheiros local

O que é afectado:Os clientes da API IWorkspace que presumem que os recursos estão armazenados no sistema de ficheiros local.

Descrição: Nas versões anteriores ao Eclipse 3.2, cada IResource existente tinha um ficheiro correspondente ou um directório num sistema de ficheiros acessível através do java.io.File. No Eclipse 3.2, foi adicionado suporte para criar recursos cujos conteúdos estão armazenados num sistema de ficheiros de apoio arbitrários. Os recursos que utilizem este suporte já não podem ser representados directamente como sendo um java.io.File.

Acção requerida: O método antigo IResource.getLocation() devolve o sistema de ficheiros local de um recurso. Este método devolve nulo para recursos que não estejam armazenados no sistema de ficheiros local. A maioria dos chamadores do getLocation() fazem-no de modo a obter uma instância do java.io.File, que já não possa ser utilizada para os recursos que não estão armazenados no sistema de ficheiros local.

O novo plug-in org.eclipse.core.filesystem faculta uma API de sistema de ficheiros genérica que pode ser utilizada em vez de java.io.File. Especialmente, uma instância do org.eclipse.core.filesystem.IFileStore faculta a maioria dos mesmos métodos que estão disponíveis no java.io.File. O fragmento seguinte de código obtém uma instância do IFileStore de um determinado recurso:

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

A tabela seguinte faculta métodos equivalentes no IFileStore para operações que são geralmente efectuadas com o java.io.File:

java.io.FileIFileStore
eliminar eliminar
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 da informação sobre um ficheiro é armazenada numa estrutura denominada IFileInfo, obtida ao chamar o IFileStore.fetchInfo(). Esta concepção permite uma maior optimização do código que utiliza o java.io.File, uma vez que uma grande parte dos atributos de um ficheiro podem ser obtidos através de uma única chamada de sistema de ficheiros. Repare que a informação contida num IFileInfo tornar-se-á obsoleta se o ficheiro subjacente for alterado e, por conseguinte, as instâncias só deverão ser mantidas enquanto forem necessárias. Seguem-se alguns métodos contidos no java.io.File que são 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 exemplo concreto, o código que anteriormente chamava java.io.File.exists() pode agora chamar IFileStore.fetchInfo().exists(). Quando um IFileInfo é modificado, é necessário armazenar o resultado através da utilização do método IFileStore.putInfo. Por exemplo, este fragmento inverte o atributo só de leitura num ficheiro

   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()

Assim como o método getLocation(), a localização da descrição do projecto pode já não se encontrar no sistema de ficheiros local. O método IProjectDescription.getLocationURI() pode ser utilizado para obter a localização de um recurso num sistema de ficheiro arbitrário.

Colocação em memória cache local

Alguns clientes têm mesmo de ter uma representação local de um ficheiro. Por exemplo, podem estar a lançar uma ferramenta nativa em relação a esse ficheiro ou a utilizar bibliotecas que não estejam conscientes do Eclipse e que apenas consigam processar recursos de sistemas de ficheiros (tal como java.util.zip.ZipFile). Nestes casos, pode requerer que um IFileStore devolva uma cópia local colocada na memória cache dos seus conteúdos:

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

Repare que quando uma cópia de um ficheiro colocada na memória cache é obtida, esta não se mantém em sincronia com o sistema de ficheiros do qual adveio. A modificação da cópia colocada na memória cache não levará à modificação do ficheiro subjacente.

Falha graciosa

Os clientes que não possam processar recursos fora do sistema de ficheiros local, podem querer adaptar o seu código para que falhe graciosamente. Os clientes podem verificar se um recurso se encontra no sistema de ficheiros local e podem ignorar o recurso ou alertar o utilizador quando encontrarem um recurso que não conseguem processar. Para determinar se um recurso se encontra no sistema de ficheiros local, é necessário encontrar o esquema do sistema de ficheiros. Este esquema pode ser obtido a partir 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 tiver a instância IFileStore em questão, pode obter o esquema da seguinte forma:

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

2. Alterações da API para o MultiPageEditorSite

O que é afectado: Os clientes que chamam o MultiPageEditorSite.progressStart() or MultiPageEditorSite.progressEnd().

Descrição: Durante o desenvolvimento do Eclipse 3.0, estes métodos foram adicionados como parte do trabalho de suporte de progresso. Antes da edição da versão 3.0, foi alterada a forma de processar o progresso e este método tornou-se desnecessário. Através de erros do programador, estes métodos públicos foram deixados para a edição da versão 3.0. Estes dois métodos nunca serviram nenhuma função numa edição do Eclipse e, por conseguinte, foram eliminados.

Action required: Clients calling MultiPageEditorSite.progressStart() or MultiPageEditorSite.progressEnd() should switch to using IWorkbenchSiteProgressService instead.

3. Alterações do conteúdo no config.ini

O que é afectado: Os clientes que contêm um config.ini personalizado e que deslocam a aplicação para a versão 3.2.

Descrição: Nas versões anteriores à 3.2, o valor comum dos osgi.bundles contidos no config.ini era org.eclipse.core.runtime@2:start, org.eclipse.update.configurator@3:start. Devido à refactorização do tempo de execução, este valor necessita de ser actualizado para que a actualização inicie com sucesso.

Acção requerida:Alterar 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 do conteúdo nas aplicações implementadas do jnlp

O que é afectado: Os clientes que implementam aplicações RCP e que especificam um valor para osgi.bundles.

Descrição: Nas versões anteriores à 3.2, o valor comum dos osgi.bundles contidos no ficheiro jnlp principal era org.eclipse.core.runtime@2:start, org.eclipse.update.configurator@3:start. Devido à refactorização do tempo de execução, este valor necessita de ser actualizado, caso contrário as NullPointerException poderiam ser lançadas, evitando que a aplicação fosse iniciada.

Acção requerida:Alterar 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. As chamadas específicas do Bundle.start() obrigam o agrupamento a ser activado no próximo reinício

O que é afectado: Os clientes que chamam o Bundle.start().

Descrição: No Eclipse, um agrupamento é especificado para ser um agrupamento de início lento através da utilização do cabeçalho Eclipse-LazyStart (ou do cabeçalho obsoleto Eclipse-AutoStart). No Eclipse 3.1, o método org.osgi.framework.Bundle.start() não marcou os agrupamentos de início lento como sendo iniciados persistentemente. Uma vez que os agrupamentos de início lento nunca foram marcados como sendo iniciados persistentemente, estes não serão automaticamente iniciados aquando do reinício do eclipse. O javadoc para Bundle.start() declara que deverá ocorrer o seguinte, quando o método é chamado:

"Registe persistentemente que este agrupamento foi iniciado. Quando o Enquadramento for reinicidado, este agrupamento tem de ser iniciado automaticamente."

No Eclipse 3.2, o método Bundle.start() foi corrigido de modo a marcar adequadamente o agrupamento como sendo iniciado persistentemente, mesmo que o agrupamento seja de início lento. Esta correcção tinha de estar em conformidade com especificação do Enquadramento OSGi. Por conseguinte, os chamadores de Bundle.start() irão obrigar o agrupamento a ser iniciado quando o Eclipse for reiniciado.Geralmente, esta acção é considerada como sendo um mau procedimento, uma vez que fará com que agrupamentos desnecessários sejam activados de cada vez que o Eclipse é iniciado. Em alguns casos, poderá provocar resultados inesperados, tais como bug 134412.

Acção requerida: Os clientes de Bundle.start() necessitam de avaliar se a intenção é activar persistentemente o agrupamento em cada reinício. Caso não seja essa a intenção, os clientes deverão encontrar uma outra forma de activar o agrupamento. Na maioria dos casos, as chamadas Bundle.start() podem ser evitadas simplesmente ao permitir que o agrupamento de destino seja activado lentamente quando as classe forem carregadas a partir delas. Existem situações raras que requerem que um agrupamento de início lento seja activado agressivamente, mas que não seja marcado persistentemente para activação num reinício. Estes tipos de situações deverão utilizar Bundle.loadClass() para carregar uma classe para o agrupamento que necessita de ser activado, em vez de chamar Bundle.start().

5. O traço de sublinhado que não é substituído por hífen nos números das versões de plug-in

No Eclipse 3.0, a utilização de um carácter de traço de sublinhado ("_") no segmento do qualificador do identificador de versão não era suportada, mas também não era executada. Se um identificador de versão de plug-in contivesse um carácter de traço de sublinhado no qualificador, este carácter era transformado em hífen ("-") ao exportar o plug-in para o sistema de ficheiros e também ao instalar o plug-in a partir de um sítio de actualização.
No Eclipse 3.1, as regras para caracteres aceites pelos qualificadores permitiam a inclusão do carácter de traço de sublinhado, para que quando um plug-in infractor fosse exportado ou instalado, o estado original do qualificador não fosse alterado. Esta alteração subtil foi acidentalmente excluída do manual de migração das versões 3.0 e 3.1. Sucede-se que (para o Eclipse 3.2) foi mantida a compatibilidade entre o Eclipse 3.1 e os plug-ins que utilizam caracteres de traço de sublinhado nos respectivos qualificadores de versões, deverão ter em conta as alterações supramencionadas ao trabalhar com versões antigas de plug-ins (ao exportá-las e quando estas existem em sítios de actualização). Isto significa, por exemplo, que os fornecedores de plug-ins que contenham versões antigas de plug-ins num sítio de actualização deverão certificar-se que o nome no sistema de ficheiros corresponde ao nome do plug-in.