Quando você precisar modificar recursos no espaço de trabalho, é importante ter em mente quais outros plug-ins podem estar trabalhando com os mesmos recursos. A API dos recursos fornece mecanismos robustos para manter os plug-ins informados sobre as alterações no espaço de trabalho e para certificar-se de que vários plug-ins não modificam o mesmo recurso ao mesmo tempo. Sempre que possível, as modificações de plug-in no espaço de trabalho devem ser colocadas em batch em unidades de trabalho dentro de um espaço de trabalho executável. Esses executáveis ajudam a reduzir a quantidade de notificações de alteração geradas pelas alterações. Eles também permitem que você declare qual parte do espaço de trabalho deve ser modificada, para que outros plug-ins possam ser impedidos de alterar a mesma parte do espaço de trabalho.
O protocolo para IWorkspaceRunnable é muito simples. Um espaço de trabalho executável parece uma operação de execução longa ou uma tarefa da plataforma. O verdadeiro trabalho é feito dentro de um método de execução, com o progresso relatado para o IProgressMonitor fornecido. O código que manipula o espaço de trabalho é executado dentro do método de execução.
IWorkspaceRunnable myRunnable = new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { //do the actual work in here ... } }
Quando for a hora de executar o código, o plug-in diz ao espaço de trabalho que execute o código em seu benefício. Assim, o espaço de trabalho pode gerar quaisquer eventos de alteração necessários e assegurar que nenhum plug-in está modificando o mesmo recurso ao mesmo tempo. (Mesmo que o seu plug-in não esteja utilizando as tarefas de segundo plano e a estrutura de coincidência para modificar o espaço de trabalho, outros plug-ins podem estar fazendo isso.)
O protocolo do IWorkspace é utilizado para executar um espaço de trabalho executável. A técnica preferida é utilizar a forma longa do método de execução que fornece uma regra de planejamento e especifica como os eventos de alteração do recurso são difundidos.
Especificar uma regra de planejamento ao executar um espaço de trabalho executável permite que o espaço de trabalho determine se as alterações de recurso entrarão em conflito com as alterações de espaço de trabalho ocorrendo em outros encadeamentos. (Consulte as Regras de planejamento para obter uma visão geral das regras de planejamento e o protocolo ISchedulingRule.) Felizmente, o protocolo IResource inclui o protocolo para ISchedulingRule, que significa que um recurso pode freqüentemente ser utilizado como uma regra de planejamento para si mesmo.
Confuso? O código pode ajudar a esclarecer este ponto. Suponha que o seu plug-in está se preparando para modificar um grupo de recursos em um projeto específico. O projeto em si pode ser utilizado como a regra de planejamento para fazer as alterações. O seguinte fragmento executa o espaço de trabalho executável que criamos anteriormente:
IWorkspace workspace = ResourcesPlugin.getWorkspace(); workspace.run(myRunnable, myProject, IWorkspace.AVOID_UPDATE, null);
O executável é transmitido para o espaço de trabalho, seguido pelo projeto que o código está manipulando. Isso diz ao espaço de trabalho que todas as alterações no executável estão confinadas em myProject. Quaisquer pedidos de outros encadeamentos para alterar myProject serão bloqueados até que este executável seja concluído. Da mesma forma, essa chamada será bloqueada se algum outro encadeamento já estiver modificando myProject. Especificando qual parte da árvore de recursos será modificada pelo executável, você estará permitindo que outros encadeamentos continuem modificando outras partes do espaço de trabalho. É importante certificar-se de que a sua regra de recurso corresponde ao trabalho sendo feito dentro do executável. Qualquer tentativa de acessar um recurso fora do escopo da regra de planejamento acionará uma exceção.
O terceiro parâmetro para o método de execução especifica se quaisquer eventos de alteração de recursos periódicos devem ser difundidos durante o escopo desta chamada. Utilizar IWorkspace.AVOID_UPDATE diz à plataforma para suprimir quaisquer eventos de alteração de recursos enquanto o executável está em execução e para difundir um evento no final das alterações. Durante essa chamada, quaisquer outros executáveis criados no executável serão considerados parte da operação de batch pai. As alterações de recurso feitas nesses executáveis aparecerão na notificação de alteração de recursos do pai.
No exemplo acima, assumimos que o código dentro do executável modificou somente recursos em um projeto específico. Isso facilitou a especificação de uma regra de planejamento do executável. Na prática, pode ser mais difícil computar quais partes do espaço de trabalho serão afetadas por uma alteração específica. Por exemplo, mover um recurso de um projeto para outro afeta os dois projetos. IResourceRuleFactory pode ser utilizado para ajudar a computar uma regra de recurso apropriada para determinados tipos de alterações de recurso. Você pode obter um depósito de informações do fornecedor da regra de recursos do espaço de trabalho em si.
IWorkspace workspace = ResourcesPlugin.getWorkspace(); IResourceRuleFactory ruleFactory = workspace.getRuleFactory();
O depósito de informações do fornecedor pode fornecer regras apropriadas para muitos tipos de operações. Se o seu executável estiver movendo um recurso de um local para outro, pode obter uma regra apropriada para esta operação:
ISchedulingRule movingRule = ruleFactory.moveResource(sourceResource, destinationResource); workspace.run(myRunnable, movingRule, IWorkspace.AVOID_UPDATE, null);
Consulte o javadoc para IResourceRuleFactory para a lista de regras disponíveis. O plug-in de recursos utiliza essas regras para implementar a maioria das operações de recursos. Procurar o código que utiliza esses métodos de regra como referência ajudará a demonstrar como eles são utilizados na prática.
Várias regras podem ser combinadas utilizando a MultiRegra.
ISchedulingRule movingRule = ruleFactory.moveResource(sourceResource, destinationResource); ISchedulingRule modifyRule = ruleFactory.modifyResource(destinationResource); workspace.run(myRunnable, MultiRule.combine(movingRule, modifyRule), IWorkspace.AVOID_UPDATE, null);
A forma curta do método de execução em IWorkspace também está disponível. É retido para compatibilidade de retrocesso. A forma curta não inclui uma regra ou um sinalizador de atualização.
workspace.run(myRunnable, null);
é efetivamente o mesmo que chamar
workspace.run(myRunnable, workspace.getRoot(), IWorkspace.AVOID_UPDATE, null);
Especificar a raiz do espaço de trabalho como a regra de planejamento colocará uma trava em todo o espaço de trabalho até que o executável seja concluído. Essa é a maneira mais conservadora de executar uma atualização do espaço de trabalho, mas não é muito amigável para outros plug-ins direcionados à coincidência.